JAVA-IO流总结

发布于 1 天前 0 次阅读 2461 字 预计阅读时间: 11 分钟 JAVA


字节流

作用 :

称之为万能流, 图片, 视频, 音频...都可以使用字节流进行操作

弊端 :

操作纯文本文件时, 内部如果有中文汉字, 就可能会出现乱码问题.

字节输入流

InputStream 抽象类

(1)FileInputStream

构造方法 :

1. public FileInputStream(String pathname)
2. public FileInputStream(File pathname)

成员方法 :

public int read() 
//一次读取一个字节,  读取到文件末尾返回 -1

public int read(byte[] bys)  
//一次读取一个字节数组
//将读取到的字节存入数组,  返回读取到的有效字节个数,   读取到文件末尾返回 -1

public void close()
//关闭流释放资源

(2)BufferedInputStream

字节缓冲输入流

字节输出流

OutputStream 抽象类

(1)FileOutputStream

构造方法 :

public FileOutputStream(String pathname)
public FileOutputStream(String pathname,  boolean append)


public FileOutputStream(File pathname)
public FileOutputStream(File pathname,  boolean append)

成员方法 :

public void write(int i)  //一次写出一个字节 
public void write(byte[] bys)  一次写出一个字节数组
public void write(byte[] bys, int off, int len) //一次写出一个字节数组的一部分
public void close()

(2)BufferedOutputStream

字节缓冲输出流

文件拷贝

FileInputStream fis = new FileInputStream("D:\\A.txt");
FIleOutputStream fos = new FileOutputStream("E:\\A.txt");

byte[] bys = new byte[1024 * 8];

int len;

while( (len = fis.read(bys)) != -1 ){
       fos.write(bys, 0, len);
}

fis.close();
fos.close();

不关流,数据写出?

Q:字节流写出数据, 如果没有调用close方法, 数据能不能写出?

A:字节流内部没有内置的缓冲区, 可以写出数据

追加写入数据

输出流关联文件

文件不存在 : 会自动创建
文件存在 : 会清空文件现有的内容, 然后再写入

如果想要实现追加写入, 需要在构造方法的第二个参数, 传入 true

字符流

作用 :

解决读取纯文本文件的中文乱码问题.

Reader输入流

FileReader

构造方法 :

public FileReader(String pathname) 
public FileReader(File pathname) 
//按照平台默认编码表进行读取

成员方法 :

public int read()
//一次读取一个字符, 读取到文件末尾返回 -1

public int read(char[] chs) 
//一次读取一个字符数组,将读取到的多个字符存入数组,返回读取到的有效字节个数,读取到末尾也是返回 -1

BufferedReader

字符缓冲输入流, 特有读取方法 :

public String readLine()
//一次读取一整行字符串, 读取到文件末尾返回 null

InputStreamReader

作用 : 可以按照指定的编码读取数据

构造方法 :

public InputStreamReader(InputStream is, String chatsetName) 
//参数1 : 字节输入流关联要读取的文件 
//参数2 : 指定编码表

成员方法 :

字符流通用的读取方法

Writer输出流

FileWriter

构造方法 :

public FileWriter(String pathname)
public FileWriter(String pathname, boolean append)

public FileWriter(File pathname)
public FileWriter(File pathname,  boolean append)

成员方法 :

public void write(int i)
//写出一个字符

public void write(char[] chs)
//写出一个字符数组

public void write(char[] chs, int off, int len)
//写出一个字符数组的一部分

public void write(String s)
//直接写出字符串

public void write(String s, int off, int len)
//写出字符串的一部分

public void flush()
//负责将缓冲区的数据刷出到文件

BufferedWriter

字符缓冲输出流, 特有的换行方法 :

public void newLine()
//写出换行符, 具有跨平台性

OutputStreamWriter

作用 : 可以按照指定的编码写出数据

构造方法 :

public OutputStreamWriter(OutputStream os, String charsetName) 
//参数1 :  字节输出流关联要写出的文件
//参数2 :  指定编码表 

成员方法 :

字符流通用的写出方法

字符流解决乱码

字符流 = (字节流 + 编码表)

铺垫 : 中文字符, 字节组成第一个肯定是负数, 后面的字节有可能是正数

读取过程 : 先读取一个字节, 判断是否是负数, 如果是负数说明正在读取中文 根据平台的默认编码表, 来决定再读取多少个字节

UTF-8 : 中文占用3个字节
GBK : 中文占用2个字节

如果是UTF-8, 再读取2个字节进行转换
如果是GBK, 再读取1个字节进行转换

但是如果读取到的第一个字节是正数, 说明读取的不是中文, 直接转换.

flush()和close()区别

铺垫 : 字符输出流中, 内置了一个char[]数组, 写出数据不会直接进入文件, 而是先到这个数组中, 也就是说, 如果只调用了write方法, 没有将数据刷出, 文件中就看不到写出的数据

flush() : 将缓冲区的数据刷出到文件的, 刷出之后可以继续写出

close() : 关闭流释放资源, 只不过再关闭之前, 会检查一下缓冲区是否有数据, 有的话, 刷出再关闭, 关流之后不允许再次写出数据了.

文件拷贝

FileReader fr = new FileReader("D:\\A.txt");
FileWriter fw = new FileWriter("E:\\A.txt");


char[] chs = new char[1024];

int len;

while((len = fr.read(chs)) != -1){
     fw.write(chs, 0, len);
}

fr.clsoe();
fw.close();
BufferedReader br = new BufferedReader(new FileReader("D:\\A.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\A.txt"));


char[] chs = new char[1024];

int len;

while((len = br.read(chs)) != -1){
     bw.write(chs, 0, len);
}

br.close();
bw.cl

文本排序

public class BufferedStreamTest1 {
    /*
        需求: 对出师表.txt进行排序
     */
    public static void main(String[] args) throws IOException {
        // 1. 创建输入流对象关联文件 (BufferedReader : 一次读取一整行)
        BufferedReader br = new BufferedReader(new FileReader("src\\com\\itheima\\day12\\出师表.txt"));

        // 2. 准备集合容器, 来存储读取到的每一行数据
        TreeSet<String> ts = new TreeSet<>();

        // 3. 读取
        String line;
        while((line = br.readLine()) != null){
            ts.add(line);
        }

        // 4. 读取完毕了关流
        br.close();

        // 5. 创建输出流对象关联文件, 将集合的数据写出去
        BufferedWriter bw = new BufferedWriter(new FileWriter("src\\com\\itheima\\day12\\出师表.txt"));
        for (String s : ts) {
            bw.write(s);
            bw.newLine();
        }

        bw.close();
    }
}
//出师表.txt
//3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
//8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
//4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
//2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
//1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
//9.今当远离,临表涕零,不知所言。
//6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
//7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
//5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

功能流

序列化流 (对象流)

作用 : 可以在流中以字节的形式操作对象

序列化

ObjectOutputStream

构造方法 :

public ObjectOutputStream(OutputStream os);

成员方法 :

public void writeObject(Object o);

反序列化

ObjectInputStream

构造方法 :

public ObjectInputStream(InputStream is)

成员方法 :

public Object readObject();

注意事项

1. 对象要想被序列化, 实现 Serializable

2. 如果实现了 Serializable 接口, 类中就会自带一份序列版本号

序列化操作的时候, 会将对象信息和版本号一并保存到文件

反序列化的时候, 会拿着类的版本号和流中的版本号进行比对 不一致, 就会抛出异常, 起到提醒的作用.

避免麻烦事儿 : 可以手动写死序列版本号 (抄作业 String ArrayList)
“抄作业”指的是参考Java标准库中类(如StringArrayList)的做法,在类中显式定义一个private static final long serialVersionUID常量

3. 如果类中的属性被 transient 进行修饰, 将不会参与序列化操作

4. 建议 : 今后对象的读写操作进行一次

打印流

(1)PrintStream

构造方法 :

public PrintStream(String pathname)
public PrintStream(File pathname)

public PrintStream(OutputStream os)
//想要追加写入的时候可以使用这个构造方法

成员方法 :

public void print(任意类型) ;

public void println(任意类型);

(2)PrintWriter