IO流总结

java的io流根据功能分为输入流和输出流。
流是单向的
输入流用于读取数据
输出流用于写出数据
输入输出的参照方向是基于程序的。即当想从程序中向文件传输数据就是输出流,将文件中的数据加载到程序中就是输入流。

流还分为高级流(过滤流)和低级流(节点流)。
高级流:不能独立存在,必须基于另一个流来工作,他可以为我们带来一些额外的功能以简化对数据的读写。
低级流:数据有明确的来源或去向。

流根据处理的单位划分为字节流(以字节为单位读取数据)和字符流(以字符为单位读取数据)。

字节流有明显的特征,即都是以Stream结尾的。
FileInputStream(read)和FileOutputStream(write)也和RandomAccessFile一样有write和read方法,

write(int d):向文件中写入一个整数,只对写入整数的低八位有效。

FileOutputStream fos = new FileOutputStream("fos.dat");
fos.write('A');
write(byte[] b):将给定的字节数组中的所有字节一次性写入文件。

<span style="font-size:18px;">String str = "这是一个字符串";
byte[] strData = str.getBytes("UTF-8");
fos.write(strData);</span>

int read():读取一个字节,并以int值的形式返回。同样只对低八位有效,读取到文件末尾是返回-1。

<span style="font-size:18px;">FileInputStream fis= new FileInputStream("fos.dat");
System.out.println((char)fis.read());</span>

int read(byte[] b):一次性尝试读取给定数组长度的字节量,并存入给定的数组b,返回值为实际读到的字节量。

<span style="font-size:18px;">byte[] array = new byte[50];
int len = fis.read(array);
System.out.println(len);
/* String(byte[] b,int start,int len,String charsetName) */
/* start表示从第几个字节开始读取,len表示从start开始读取多少长度 */
String str = new String(array, 0, len, "UTF-8");
System.out.println(str);</span>

当文件已存在且有内容时,再调用FileOutputStream的write方法时,就会覆盖掉原有的内容。这时就可以使用FileOutputStream的构造方法FileOutputStream(String fileName,boolean append),来确定对原文件是追加还是覆盖,append为true时,是在原文件的末尾追加,append为false时,是将原文件中内容覆盖。

BufferedInputStream和BufferedOutputStream,高级流。
BufferedInputStream:缓冲字节输入流。
BufferedOutputStream:缓冲字节输出流。
这两个流属于高级流,必须基于另一个流工作。在它们内部有一个缓存区,每次读或写的过程都是先将数据写入到缓存区,待缓存区满了再将数据写出到文件或读取到程序。所以在程序结束时必须调用close()方法关闭流,close()方法会自动将缓存区中的数据刷新出缓存区。

<span style="font-size:18px;">FileOutputStream fos = new FileOutputStream("bos.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
String str = "hello";
byte[] data = str.getBytes("UTF-8");
bos.write(data);
bos.close();</span>

DataInputSream和DataOutputSream,数据输入输出流,高级流。
DataInputSream:可以很方便的读取基本类型数据。
DataOutputSream:可以很方便的写出基本类型数据。
DataOutputSream可以提供writeXxx(Xxx x)方法对基本数据类型进行序列化。
DataInputSream可以提供readXxx()方法对基本数据类型进行反序列化。
写出:

<span style="font-size:18px;">FileOutputStream fos = new FileOutputStream("dos.dat");
DataOutputStream dos = new DataOutputStream(fos);
int num = 97;
dos.writeInt(num);
dos.writeLong(12345l);
dos.writeDouble(1.2345);
dos.writeChar(65);
dos.writeUTF("你好");
dos.close();</span>
读取:

<span style="font-size:18px;">FileInputStream fis = new FileInputStream("dos.dat");
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readDouble());
System.out.println(dis.readChar());
System.out.println(dis.readUTF());
dis.close();</span>


对象序列化。对象的序列化也是需要将其存储在文件上,可以将这个文件进行传输,再需要的时候进行反序列化。
利用ObjectOutputStream和ObjectInputStream对其进行序列化和反序列化
具体代码如下:
序列化:

Person person = new Person("Jack", 25, 'F', "google", 9999.99, false);
FileOutputStream out = new FileOutputStream("file/person.obj");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
objectOutputStream.writeObject(person);
objectOutputStream.close();
反序列化:

FileInputStream in=new FileInputStream("file/person.obj");
ObjectInputStream objectInputStream=new ObjectInputStream(in);
Person person=(Person)objectInputStream.readObject();
System.out.println(person);
objectInputStream.close();


高级流可以叠加使用。

字符流:以字符为单位处理数据,一次处理一个字符unicode,其实底层本质上还是读写字节,也是高级流,必须基于另一个流工作字符流有明显的特征,即是以Reader和Writer结尾的。

Reader:所有字符输入流的父类
Writer:所有字符输出流的父类

OutputStreamWriter的write()方法有以下几种(同FileOutputStream的write方法相似):
void write(int d):写一个字符(char),写给定的int值的“低16位”。
void write(char[] c):一次性将给定的字符数组中的所有字符写出。
void write(char[] c,int start,int len):将给定的字符数组中从start处开始连续将len个字符写出。
void write(String str):将给定的字符串转换为字节后写出。
void write(String str,int start,int len):将给定的字符串中从start处开始连续将len个字符写出。
默认情况下,write方法会将当前字符串按照系统默认的字符集转换为字节后写出。
OutputStreamWriter有一个构造方法可以使用给定的字符集将字符写出。

<span style="font-size:18px;">FileOutputStream fos = new FileOutputStream("osw2.txt",true);
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
osw.write("大家好!");
osw.close();</span>

InputStreamReader的read方法有以下几种
int read():读取一个字符,以int值形式返回,该int值“低16位”有效。
int read(char[] c):一次性最多尝试读取给定数组的length个字符,并存入数组,返回值为实际读取到的字符量。
不能直接读取字符串,因为不知道字符串的长度,所以不知道从哪里结束。


使用指定字符集读取字符。

<span style="font-size:18px;">FileInputStream fis = new FileInputStream("osw2.txt");
InputStreamReader isr = new InputStreamReader(fis,"GBK");</span>

BufferedWriter:缓冲字符输出流,高级流,必须基于一个字符输出流工作。

<span style="font-size:18px;">FileOutputStream fos = new FileOutputStream("bw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
BufferedWriter bw = new BufferedWriter(osw);
bw.write("你好!");
bw.close();</span>


BufferedReader:缓冲字符输入流,可以以行为单位读取字符串。高级流,必须基于一个字符输出流工作。
它有一个方法String readLine():一次读取一行字符串,连续读取若干字符,直到读取到“换行符”为止,返回的字符串中不包含换行符。

他还有一个int read()方法:每次读取单个字符。返回-1时表示读取到流的末尾。可以用来判断流是否读取完毕。

 

FileWriter和FileReader:可以直接读写文本文件的字符流。

FileWriter的构造方法与FileOutputStream的构造方法一样,都支持传入一个文件FileWriter(File file)或直接传入一个文件名FileWriter(String fileName)
使用FileWriter或FileReader对文件写字符或读字符都默认许可使用当前系统默认的字符集进行读写。

<span style="font-size:18px;">FileWriter writer = new FileWriter(new File("fw.txt"));
BufferedWriter bw = new BufferedWriter(writer);
bw.write("呵呵");
bw.close();</span>

 

Reader的读取read()每次都只读取一个字符。

 

PrinterWriter支持一下构造方法:
PrintWriter(File file)
PrintWriter(String fileName)
PrintWriter(Writer writer)

PrintWriter(OutputStream out),不带自动行刷新
PrintWriter(OutputStream out,String charsetName),在写文件时指定字符集
PrintWriter(OutputStream out,boolean autoflush)
此构造方法可以创建一个带有自动行刷新的缓冲字符输出流,每当调用println()时,就会自动刷新。但是print()不行,必须有换行符才会自动刷新。

<span style="font-size:18px;">PrintWriter pw = new PrintWriter(fos, true);
pw.println("呵呵");
// 必须有换行时才会自动行刷新,如果是print("呵呵"),是不会执行自动刷新的</span>

 

有了PrintWriter后就可以不用使用BufferedWriter了,因为PrintWriter有BufferedWriter的所有功能
PrintWriter有write()方法,但是还有print()和println()方法,后者比前者更好用。

<span style="font-size:18px;">PrintWriter writer = new PrintWriter(new File("pw.txt"), "GBK");
writer.println("How are you?");</span>

 

FileOutputStream负责写文件,字符流负责设置字符集,PrintWriter负责自动行刷新并写字符串。

 

用于对象序列化与反序列化的流
ObjectInputStream:对象反序列化
ObjectInputStream有readObject()方法
ObjectOutputStream:对象序列化
ObjectOutputStream有writeObject(Object obj)方法
所有需要序列化的类,都必须是Serializable的实现类。
Serializable是一个空接口,里面没有任何方法,他的作用在于标记类可以被序列化。

transient关键字,被该关键字修饰的属性在序列化时其值被忽略
当我们不关心序列化前后属性的值时就可以将其设置为transient

何时需要对对象序列化和反序列化?
有两种情况。一是用于保存对象,二是用于传输。

<span style="font-size:18px;">Person person = new Person("Tom", 20, 1);
FileOutputStream fos = new FileOutputStream("person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(person);
oos.close();
FileInputStream fis = new FileInputStream("person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
Person person2 = (Person) ois.readObject();// 反序列化后的对象不是原来的对象,==比较为false,equals比较为true
System.out.println(person2);
System.out.println(person == person2);//false
System.out.println(person.equals(person2));//true
ois.close();</span>


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值