Java字节流用法详解
所谓 IO 流,即通过输入输出流完成对文件的读写。例如,用 Java 程序把 D 盘的文件复制到 F 盘,就可以通过 IO 流来实现。
I 是指 input,表示输入的意思;O 是指 Output,表示输出的意思。初学者很容易把这里的输入输出搞混,如何去判断使用输入流还是输出流呢?你只需要站在程序的角度去看待问题,把自己比作程序,首先将 D 盘文件读取到程序中,再由程序将文件的数据流写到 F 盘中。所以读取目标文件就是输入流,写入 F 盘就是输出流,如下图所示。
图 1 IO流
图 1 中数据流的走向要搞清楚,流是一种以先进先出的方式传输数据的序列,Java 中的流有很多种不同的分类。
本节我们先来看字节流,它是指以字节为单位来操作数据。
打个比方,有一口装满水的水缸和一口空缸,现在要把满缸的水舀到空缸中。舀水需要水瓢,水瓢的大小决定了每次转移水的分量。文件资源就相当于水缸,数据就相当于水,流就相当于水瓢,字节流就是每次只能舀一字节水量的水瓢。
字节流按照方向又可以分为输入字节流(InputStream)和输出字节流(OutputStream),InputStream 是 java.io 包中的顶层父类,并且是一个抽象类,定义为:
实际开发中不能直接实例化 InputStream 类的对象,应该实例化其实现了抽象方法的子类 FileInputStream,定义为:
OutputStream 跟 InputStream 类似,也是一个抽象父类,定义为:
我们在使用 OutputStream 进行写操作时,不能直接实例化 OutputStream 类的对象,应该实例化其实现了抽象方法的子类 FileOutputStream,定义为:
I 是指 input,表示输入的意思;O 是指 Output,表示输出的意思。初学者很容易把这里的输入输出搞混,如何去判断使用输入流还是输出流呢?你只需要站在程序的角度去看待问题,把自己比作程序,首先将 D 盘文件读取到程序中,再由程序将文件的数据流写到 F 盘中。所以读取目标文件就是输入流,写入 F 盘就是输出流,如下图所示。
图 1 IO流
图 1 中数据流的走向要搞清楚,流是一种以先进先出的方式传输数据的序列,Java 中的流有很多种不同的分类。
- 按照方向分,可以分为输入流和输出流;
- 按照单位分,可以分为字节流和字符流,字节流指每次处理数据是以字节为单位的,字符流是指每次处理数据是以字符为单位的;
- 按照功能分,可以分为节点流和处理流;
本节我们先来看字节流,它是指以字节为单位来操作数据。
打个比方,有一口装满水的水缸和一口空缸,现在要把满缸的水舀到空缸中。舀水需要水瓢,水瓢的大小决定了每次转移水的分量。文件资源就相当于水缸,数据就相当于水,流就相当于水瓢,字节流就是每次只能舀一字节水量的水瓢。
字节流按照方向又可以分为输入字节流(InputStream)和输出字节流(OutputStream),InputStream 是 java.io 包中的顶层父类,并且是一个抽象类,定义为:
public abstract class InputStream implements Closeable{}可以看到 InputStream 实现了 Closeable 接口,该接口的作用是每次操作结束之后完成资源释放,InputStream 常用方法如下表所示。
方 法 | 描 述 |
---|---|
public abstract int read() throws lOException | 以字节为单位读取数据 |
public int read (byte b[]) throws lOException | 将数据存入 byte 类型数组中,并返回数据长度 |
public int read (byte b[], int off, int len) throws lOException | 将数据存入 byte 类型数组的指定区间中,并返回数据长度 |
public byte[] readAIIBytes() throws lOException | 将数据存入 byte 类型数组中返回 |
public int available() throws lOException | 返回当前数据流中未读取的数据个数 |
public void close() throws lOException | 关闭数据流 |
实际开发中不能直接实例化 InputStream 类的对象,应该实例化其实现了抽象方法的子类 FileInputStream,定义为:
public class FileInputStream extends InputStream{}下面的实例程序演示了 InputStream read() 的用法:
public class IOTest { public static void main(String[] args) { try { InputStream inputStream = new FileInputStream("/Users/southwind/Desktop/ test.txt"); int temp = 0; System.out.println("当前未读取的数据个数:"+inputStream.available()); while((temp = inputStream.read())!=-1) { System.out.println(temp+",当前未读取的数据个数:"+inputStream.available()); } inputStream.close(); System.out.println("*****************************"); inputStream = new FileInputStream("/Users/southwind/Desktop/test.txt"); byte[] bytes = new byte[6]; int length = inputStream.read(bytes); System.out.println("数据流长度:"+length); System.out.println("遍历byte数组"); for (byte b : bytes) { System.out.println(b); } inputStream.close(); System.out.println("*****************************"); inputStream = new FileInputStream("/Users/southwind/Desktop/test.txt"); bytes = new byte[10]; length = inputStream.read(bytes,2,6); System.out.println("数据流长度:"+length); System.out.println("遍历byte数组"); for (byte b : bytes) { System.out.println(b); } inputStream.close(); System.out.println("*****************************"); inputStream = new FileInputStream("/Users/southwind/Desktop/test.txt"); bytes = inputStream.readAllBytes(); System.out.println("遍历byte数组"); for (byte b : bytes) { System.out.println(b); } inputStream.close(); } catch (FileNotFoundException e) { } } }运行程序,可以看到 test.txt 中的数据是“ioc”这 3 个字符,转换成 byte 类型的值为 105、111、99,程序的运行结果为:
当前未读取的数据个数:3
105,当前未读取的数据个数:2
111,当前未读取的数据个数:1
99,当前未读取的数据个数:0
*****************************
数据流长度:3
遍历byte数组
105
111
99
0
0
0
*****************************
数据流长度:3
遍历byte数组
0
0
105
111
99
0
0
0
0
0
*****************************
遍历byte数组
105
111
99
OutputStream 跟 InputStream 类似,也是一个抽象父类,定义为:
public abstract class OutputStream implements Closeable, Flushable{}可以看到 OutputStream 除了实现 Closeable 接口之外,还实现了 Flushable 接口。Flushable 接口可以将缓冲区的数据同步到输出流中,保证数据的完整性,OutputStream 的常用方法如下表所示。
方 法 | 描 述 |
---|---|
public abstract void write(int b) throws lOException | 以字节为单位写数据 |
public void write(byte b[]) throws lOException | 将 byte 类型数组中的数据写出 |
public void write(byte b[], int off, int len) throws lOException | 将 byte 类型数组中指定区间的数据写出 |
public void flush() throws lOException | 可以强制将缓冲区的数据同步到输出流中 |
public void close() throws lOException | 关闭数据流 |
我们在使用 OutputStream 进行写操作时,不能直接实例化 OutputStream 类的对象,应该实例化其实现了抽象方法的子类 FileOutputStream,定义为:
public class FileOutputStream extends OutputStream{}接下来,我们学习对 OutputStream 各种常用方法的使用,比如下面的实例程序演示了 write(int b) 方法的使用:
public class IOTest { public static void main(String[] args) { try { OutputStream outputStream = new FileOutputStream("/Users/southwind/Desktop/ test2.txt"); outputStream.write(99); outputStream.flush(); outputStream.close(); } catch (IOException e) { } } }程序中实现了在桌面创建文件 test2.txt,并且向文件中写入 byte 类型的数据 99。而 byte 类型的数据会转换成字符,99 对应的是’c’,所以运行结果是我们会在桌面看到 test2.txt,打开它可以看到内容为 c。