首页 > 编程笔记

Java字节流用法详解

所谓 IO 流,即通过输入输出流完成对文件的读写。例如,用 Java 程序把 D 盘的文件复制到 F 盘,就可以通过 IO 流来实现。

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。

推荐阅读

副业交流群 关注微信公众号,加入副业交流群,学习变现经验,交流各种打法。