52.常用IO流之间的关系

常用IO流之间的关系以及补充:

一、IO流关系

抽象类 InputStream OutputStream Reader Writer
抽象类的实现子类 FileInputStream FileOutputStream InputStreamReader(InputStream 字节流到字符流的桥梁)、FileReader【继承自InputStreamReader】 OutputStreamWriter(OutputStream 字符流到字节流的桥梁)、FileWriter【继承自OutputStreamWriter】
抽象类对应的增强子类 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
升级IO流的关系.png
所有流关系.png

二、【InputStream】【Reader】的指针偏移操作

注意:偏移量不能超过文件所在范围,否则会抛错

  • 【正向】StringIndexOutOfBoundsException
  • 【反向】IOException

1.InputStream字节进行偏移

InputStream的偏移操作很适合文件的断点续传功能
直接操作BufferedInputStream的反向偏移是无效的

InputStream reader = new FileInputStream("day_11\\a.txt");
byte[] b = new byte[6];

// 让指针进行正向偏移【当前位置】
long off = reader.skip(3);
int len = reader.read(b);
System.out.println("偏移:" + off + " 内容:\n" + new String(b, 0, len));

// 让指针进行反向偏移【当前位置】
off = reader.skip(-9);
len = reader.read(b);
System.out.println("偏移:" + off + " 内容:\n" + new String(b, 0, len));
reader.close();

2.Reader字符进行偏移

  • 根据指定的字符编码对应的字符个数进行偏移【不是字节个数】
  • 只能为>0的long类型数!
// 字符流的指针偏移(按照指定编码字符进行偏,比如UTF-8的中文,skip(1),对于中文就会偏移3个字节,基本ASCII一个字节)
Reader fr = new FileReader("day_11\\a.txt");
char[] c = new char[20];

// 指针从当前位置开始偏移(最开始从0开始,不能为负数!)
long off = fr.skip(4);
int len = fr.read(c);
System.out.println("偏移:" + off + " 内容:\n" + new String(c,0, len));

3.场景应用:读取一个非常大的日志文件的最后一行内容

假设JVM运行时的编码与文件编码一致;日志文件换行符与平台操作系统换行符一致!

注意: 不要使用BufferedInputStream,因为他的反向偏移无效

文本文件

第一行123456789
第二行123456789
第三行123456789
第四行123456789
第五行123456789
.
.
.
这个是最后一行123456780

Java

File file = new File("day_11\\a.txt");
FileInputStream in = new FileInputStream(file);

int n = 2;
byte[] b = new byte[n];

in.skip(file.length());
while (true) {
    in.skip(-n);
    in.read(b);
    String[] temp = new String(b).split(System.lineSeparator());
    if(temp.length > 1 && !temp[1].equals("")){
        System.out.println(temp[1]);
        break;
    }
    n *= 2;
    b = new byte[n];
}

执行结果

这个是最后一行123456780

你可能感兴趣的:(52.常用IO流之间的关系)