day21-Java IO流(字符流/装饰设计模式)

2017-02-14  本文已影响82人  苦笑男神

21.01_字符流FileReader

FileReader fr = new FileReader("xo.txt");  //可能FileNotFoundException

int c ;
while( (c = fr.read()) != -1) {  //通过项目默认的码表,一次读取一个字符
    System.out.print((char)c);
}
 
fr.close(); //可能IOException

21.02_字符流FileWriter

FileWriter fw = new FileWriter("xo.txt", true);  // true 是否追加到文本末尾

fw.write("--我会追加文本末尾--");
fw.write(97);  // 97 就是字母a
fw.close();

21.03_IO流(字符流的拷贝)

FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");

int c ;
while ( (c = fr.read()) != -1) {
    fw.write(c);
}

fr.close();
fw.close();   // Writer类中有2K的缓冲区,如果不关流,就有可能出现缓冲区的内容没有写到文件里

21.04_什么情况下使用字符流

21.05_字符流是否可以拷贝非纯文本的文件

21.06_自定义字符数组的拷贝

// 自定义小数组
FileReader fr = new FileReader("xo.txt");
FileWriter fw=  new FileWriter("a.txt");

char[] data = new char[1024 * 10];
int len;
while( (len = fr.read(data)) != -1) {
    fw.write(data, 0, len);
}
fr.close();
fw.close();

21.07_IO流(带缓冲的字符流)

BufferedReader br = new BufferedReader(new FileReader("xo.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
int c ;
while( (c = br.read()) != -1) {  //read一次,会先将缓冲区读满,从缓冲去中一个一个的返给临时变量ch
    bw.write(c); //write一次,是将数据装到字符数组,装满后再一起写出去
}

br.close();
bw.close();

21.08_readLine()和newLine()方法

// 带缓冲区的特殊方法: readLine()   newLine()
BufferedReader br = new BufferedReader(new FileReader("xo.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));

String line ;

while( (line = br.readLine()) != null) {  //读取一行,以 \r 或 \n 为换行标识
    bw.write(line);
    // bw.write("\r\n");  这个也是换行,但是只支持windows系统
    bw.newLine(); // 这个换行是跨平台的
}

br.close();
bw.close();

21.09_将文本反转

// 文本反转
BufferedReader br = new BufferedReader(new FileReader("xo.txt"));
ArrayList<String> list = new ArrayList<>();
// 将读取的数据存储到集合中
String line ;
while( (line = br.readLine()) != null) {
    list.add(line);
}
br.close();

// 倒着遍历集合,将数据写到文件上
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt",true));
for (int i = (list.size() - 1); i >= 0; i--) {
    bw.write(list.get(i));
    bw.newLine();
}
bw.close();

21.10_LineNumberReader

LineNumberReader lr = new LineNumberReader(new FileReader("xo.txt"));
lr.setLineNumber(100);  //设置行号,那么后续的行号,将是此值的递增
String line;
while((line = lr.readLine()) != null) { 
    System.out.println(lr.getLineNumber() + " " +line);  // getLineNumber获取行号,从101开始
}

lr.close();

21.11_装饰设计模式

23种设计模式之一,英文叫Decorator Pattern,又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。(Java IO流是典型的装饰设计模式)

interface Coder {
    public void coder();  // 编码技能
}

class Student implements Coder {
    public void coder() {
        System.out.println("学生学会了编码技能...");
    }
}

class PeiXunStudnet implements Coder {  //培训过的学生 ,不是通过继承实现的扩展
    private Student s ;
    
    public PeiXunStudnet(Student s) {  //装饰模式,一般通过构造方法获取被装饰的类
        this.s = s ;
    }
    
    // getter 和 setter 方法
    public Student getS() { return s;}
    public void setS(Student s) { this.s = s;}

    // 对学生进行升级
    public void coder() {
        s.coder();  //学生已经学会的技能 , 下面对学生进行技能扩展..
        System.out.println("学生学会了 ssh");
        System.out.println("学生学会了 高级数据库编程");
    }
}

21.11_装饰设计模式 和 继承的区别

装饰设计模式:
当想要对已有的对象进行功能增强时,
可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。
那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接收被装饰的对象。
并基于被装饰的对象的功能,提供更强的功能。

而继承是通过成为某个类的子类,实现功能的扩展。
所以:装饰模式比继承要灵活。避免了继承体系臃肿(降低了继承造成的耦合)。而且降低了类于类之间的关系。
装饰模式的缺点: 导致程序中出现许多小类,过度使用会使程序变的复杂。

21.12_使用指定的码表读写字符)

// 指定码表读写字符,注意,后面的码表,不分大小写
InputStreamReader ir = new InputStreamReader(new FileInputStream("utf-8.txt"),"utf-8");
OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");

int c ;
while( (c = ir.read()) != -1) {
    ow.write(c);
}
ow.close();
ir.close();

// 使用包装类,带缓存和指定编码表的读写
BufferedReader br = new BufferedReader(new InputStreamReader(
        new FileInputStream("utf-8.txt"), "UTF-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream("gbk.txt"),"GBK"));
int c ;
while( (c = br.read()) != -1) {
    bw.write(c);
}       
br.close();
bw.close();

21.13_转换流图解

转换流.png

其实这个地方应该很好理解的,读写文件有字节流和字符流。我想使用字节流读写文件,但是写文件时候,我需要另外一种编码格式,所以肯定需要一个 字节流和字符流互相转换的类,既然互相转换,所以肯定得有个 编码表 来依照参考。InputStreamReaderOutputStreamWriter就是互相转换字节流和字符流的类,因为二者继承于 ReaderWriter,所以属于字符流体系下。

21.14_获取文本上字符出现的次数

BufferedReader br = new BufferedReader(new FileReader("xo.txt"));
TreeMap<Character, Integer> map = new TreeMap<>();

int c ;
while( (c = br.read()) != -1) {   //注意这里的强制类型转换
    map.put((char) c, map.containsKey((char)c) ? map.get((char)c)+1 : 1);
}
br.close();

BufferedWriter bw = new BufferedWriter(new FileWriter("times.txt"));
// 双列集合Map的遍历
for (Character key : map.keySet()) {
    switch (key) {  //注意下面的转义的使用
    case '\t':
        bw.write("\\t" + "-->" + map.get(key) + "次");  
        break;
    case '\n':
        bw.write("\\n" + "-->" + map.get(key) + "次");  
        break;
    case '\r':
        bw.write("\\r" + "-->" + map.get(key) + "次");  
        break;
    case ' ':
        bw.write("空格" + "-->" + map.get(key) + "次");  
        break;
    default:
        bw.write(key + "-->" + map.get(key) + "次");
        break;
    }
    bw.newLine();
}
bw.close();

21.15_IO流(试用版软件)

当我们下载一个试用版软件,没有购买正版的时候,每执行一次就会提醒我们还有多少次使用机会用学过的IO流知识,模拟试用版软件,试用10次机会,执行一次就提示一次您还有几次机会,如果次数到了提示请购买正版

核心代码:
BufferedReader br = new BufferedReader(new FileReader("config.txt"));
String line = br.readLine();
br.close();
int num = Integer.parseInt("10"); //将数字字符串转为int 
// 注意,下面这句,不能写到readLine()之前,因为构造Writer会清空源文件内容
BufferedWriter bw = new BufferedWriter(new FileWriter("config.txt"));
bw.write("8");
bw.close();   // close()千万千万不能忘记!!!!

21.16_递归,方法自己调用自己

递归通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

注意

阶乘递归
public int fun(int num) {  //三目不好理解,可以转为if
    return num == 1 ? 1 : num * fun(num - 1);
}

整数递减求和
public int sum(int x) { //三目不好理解,可以转为if
    return x > 0 ? x + sum(x-1) : x ;
}

21.17_File类(递归练习)

/**
 * 递归获取 文件夹及其子目录下的java文件
 * @param file 文件夹路径
 */
public static void printJavaFile(File file) {
    File list[] = file.listFiles();
    for (File subFile : list) {
        if (subFile.isFile() && subFile.getName().endsWith(".java")) {
            System.out.println(subFile);
        }else if (subFile.isDirectory()){  //是文件夹,就进入递归
            printJavaFile(subFile);
        }
    }
}

21.18_IO流(总结)

END。
我是小侯爷。
在魔都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。

上一篇下一篇

猜你喜欢

热点阅读