-
- 2.1. 字符打印流PrintWriter
-
- 3.1. 对象序列化流ObjectOutputStream
- 3.2. property类和io流的配合使用
io流
java输入输出流(IO流)可以用来读写文件,网络连接等。
而io流又分为字节流和字符流。
1. 字节流
基类是InputStream和OutputStream,分别表示输入和输出字节流。
其中几个常用的方法:
输入流
1 | abstract int read()//从数据中读入一个字节 |
输出流
1 | abstract void write(int n)//写出一个字节的数据 |
如果需要读写文件,则需要文件字节流FileInputStream和FileoutputStream
构造器中需要提供一个路径或File对象,可以指定是否为追加模式
1 | public class fileinout { |
为了提高读取效率,可以使用缓冲流(BufferedOutputStream)来包装字节流,它只提供缓冲区,需要在其构造器中提供一个字节流。
1 | BufferedOutputStream bs = new BufferedOutputStream(new FileOutputStream("D:\\Core java2\\4.txt")); |
字节流可以复制任意类型的数据,一般采用字节缓冲流来一次读取一个字节数组的方式,效率更高
下面例子为复制文件
1 | public class copy { |
2. 字符流 = 字节流+编码
在用字节流来读取汉字时,可能会出现问题,因为默认UTF-8编码中汉字占三个字节,字节流一次读取一个字节可能会出现乱码,这时候可以采用字符流。
字符流大多数用来读写文本文件,其基类为Reader和Writer。文件字符流为
OutputStreamWriter和InputStreamReader,字符流以Writer或Reader结尾,字节流以Stream结尾。
要构造一个字符流,需要在其构造器中给定一个字节流!可以在构造器中指定编码方式。
1 | OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("D:\\Core java2\\4.txt", true), "UTF-8"); |
字符流的操作和字节流基本相同,其也有字符缓冲流BufferedReader和BufferedWriter,不过这两个流拥有特殊的方法
1 | String readLine()//读一行字符串并返回,读到换行符为止,忽略空格 |
newLine方法可以写入一个换行符,由于操作系统不同,换行符也不同,在windows系统中,换行符为‘\t\n’,newLine可以写入一个适用于各个系统的换行符!
FileReader和FileWriter可以代替OutputStreamWriter和InputStreamReader,其构造器中只需要提供文件的路径就可以了,无须再提供一个字节流。
一般采用字符缓冲流的特有方法来读写文本文件
1 | FileWriter fw = new FileWriter("D:\\Core java2\\4.txt",true); |
此时注意到代码中有一个flush方法,该方法为刷新缓冲区。close方法会先刷新缓冲区然后再关闭资源。
如果不刷新缓冲区,数据就还留在缓冲区内并没有写出。
字符流和缓冲流都需要刷新缓冲区。
2.1. 字符打印流PrintWriter
该流能够以文本格式打印给定的值,格式类似于标准输出流
1 | void print() |
3. File类
File类的构造器中需要给定一个路径
1 | File f = new File("D:\\Core java2"); |
可以利用该类来操纵文件
1 | f.createNewFile();//创建一个空文件,如果文件已存在就抛出异常 |
还可以获取文件信息
1 | f1.isFile();//是否为文件 |
下面来利用File类来访问一个路径并打印所有文件的名称
1 | public class file { |
结果会打印出该路径下所有文件的名称。
3.1. 对象序列化流ObjectOutputStream
对象序列化就是将对象保存在磁盘或者在网络中传输对象。反序列化就是从磁盘中读取出一个对象。
对象序列化流就是用来操纵对象并对其进行序列化,被序列化的类需要实现
Serializable接口,该接口只是个标志,没有方法
下面看个例子,以一个测试类为例
测试类
1 | public class Demo implements Serializable { |
序列化和反序列化操作
1 | public class object { |
为什么会输出sucker 0呢?不应该输出sucker 20吗?
- 因为测试类中的私有字段age被transient关键字修饰了,代表该字段不参与序列化。
注意:如果对象在被序列化之后再被修改了,进行反序列化时会抛出异常!
解决方案:给定序列化id。每个类都有个序列化id,如果被修改了,序列化id也会改变,进行反序列化时如果序列化id与之前不匹配,会抛出异常。如果给定了序列化id,就不会抛出异常。
下面就是给定序列化id
1 | private static final long serialVersionUID = 42L;//名字都是固定的 |
对象序列化流可以保存和传输对象。
3.2. property类和io流的配合使用
property类可以将属性映射保存在流中。
4. 总结
io流中还有许多的类,在这只是列举了常用的类。
字节流为读取字节,字符流读取字符。
字符流使用了缓冲区,需要刷新缓冲区。
使用io流的三个步骤
- 创建流对象
- 进行读写操作
- 关闭流