你的位置:首页 > Java教程

[Java教程]【JAVA I/O】字节流InputStream/OutputStream


字节流InputStream/OutputStream

本篇将对JAVA I/O流中的字节流InputStream/OutputStream做个简单的概括:

总得来说,每个字节流类都有一个对应的用途,如下:

  • ByteArrayInputStream/ByteArrayOutputStream     //字节数组相关
  • FileInputStream/FileOutputStream                        //文件操作相关
  • PipedOutputStream/PipedInputStream                  //线程间通信(管道)    
  • BufferedInputStream/BufferedOutputStream         //装饰其它字节流,增加缓冲功能                 
  • FilterInputStream/FilterOutputStream                    //装饰其它字节流,增加一些过滤处理
  • PushbackInputStream                                           //装饰其它字节流,增加回退读取功能            
  • DataOutputStream/DataInputStream                     //装饰其它字节流,增加对JAVA基本数据类型的读取/写入功能        
  • PrintStream                                                           //装饰其它字节流,增加格式化数据写入功能
  • ObjectInputStream/ObjectOutputStream               //装饰其它字节流,增加对象的序列化,以字节形式读取/写入到本地文件
  • SequenceInputStream                                           //以串行形式连接若干字节输入流

再看下字节流InputStream/OutputStream的组成结构,如下图;

接下来逐个介绍;

ByteArrayInputStream/ByteArrayOutputStream

简单地说,就是字节数组与字节输入输出流之间的各种转换,举个例子如下:

package io;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;public class IOTest {  public static void main(String[] args) throws IOException {    //内存中的字节数组    byte[] bArr = new byte[]{1,2,3};        //字节输入流    InputStream is = new ByteArrayInputStream(bArr);    //字节输出流    ByteArrayOutputStream bos = new ByteArrayOutputStream();    byte[] bff = new byte[3];    //从输入流中读取字节    is.read(bff,0,3);    System.out.println(bff[0] + "," + bff[1] + "," + bff[2]);    //往字节输出流中写入字节数组    bos.write(bff);    //从输出流中获取字节数组    byte[] bArryFromOs = bos.toByteArray();    System.out.println(bArryFromOs[0] + "," + bArryFromOs[1] + "," + bArryFromOs[2]);      is.close();
bos.close(); }}

FileInputStream/FileOutputStream

可以用FileInputStream/FileOutputStream对文件进行写入及读取,如下代码,可以实现文件的复制:

package io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class IOTest {  public static void main(String[] args) throws IOException {    // 字节输入流    InputStream is = new FileInputStream("C:\\test.jpg");    // 字节输出流    OutputStream os = new FileOutputStream("C:\\copy_test.jpg", false);    int bTmp = -1;    while ((bTmp = is.read()) != -1) {      os.write(bTmp);    }    is.close();    os.close();  }}

PipedOutputStream/PipedInputStream

可用于同一个JVM中的两个线程间通信,字节流传输,举个例子:

package io;import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class IOTest {  public static void main(String[] args) throws IOException {        final PipedOutputStream pos = new PipedOutputStream();    final PipedInputStream pis = new PipedInputStream(pos);    ExecutorService es = Executors.newFixedThreadPool(2);    es.execute(new Runnable() {      @Override      public void run() {        try {          byte[] bArr = new byte[]{1,2,3};          pos.write(bArr);          pos.close();        } catch (IOException e) {          e.printStackTrace();        }      }    });    es.execute(new Runnable() {      @Override      public void run() {        byte[] bArr = new byte[3];        try {          // 会导致线程阻塞          pis.read(bArr, 0, 3);          pis.close();        } catch (IOException e) {          e.printStackTrace();        }        System.out.println(bArr[0] + "," + bArr[1] + "," + bArr[2]);              }    });  }}

BufferedInputStream/BufferedOutputStream

带缓冲区的字节流,装饰器模式在jdk中的一个应用,可用于装饰其它字节流;

一次读取/写入一大块字节到缓冲区,避免每次频繁访问外部媒介,提高性能;

下面是一个例子:

package io;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class IOTest {  public static void main(String[] args) throws IOException {    // 字节输入流    BufferedInputStream is = new BufferedInputStream(new FileInputStream("C:\\test.jpg"), 10 * 1024);    // 字节输出流    BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("C:\\copy_test.jpg", false));    int bTmp = -1;    while ((bTmp = is.read()) != -1) {      os.write(bTmp);    }    is.close();    os.close();  }}

FilterInputStream/FilterOutputStream

可装饰其它字节流,实现自定义过滤字节流的基类,基本上是简单的覆盖了InputStream/OutputStream中的方法,意义不是很大;

PushbackInputStream

可装饰其它字节输入流,增加的功能是是回退读取,如下例子:

package io;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.PushbackInputStream;public class IOTest {  public static void main(String[] args) throws IOException {    byte[] bArr = new byte[] { 1, 2, 3 };        // 字节输入流    PushbackInputStream pis = new PushbackInputStream(new ByteArrayInputStream(bArr));    System.out.println(pis.read());    System.out.println(pis.read());    // 回退    pis.unread(1);    System.out.println(pis.read());    pis.close();  }}

DataOutputStream/DataInputStream

可装饰其它字节输入流,增加从输入流中读取Java基本类型数据的功能;

举个例子:

package io;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class IOTest {  public static void main(String[] args) throws IOException {    // 字节输入流        DataOutputStream dos = new DataOutputStream(new FileOutputStream("C:\\data.data"));    DataInputStream dis = new DataInputStream(new FileInputStream("C:\\data.data"));        dos.writeDouble(2.0235);    dos.writeInt(520);    dos.flush();        System.out.println(dis.readDouble());    System.out.println(dis.readInt());    dos.close();    dis.close();  }}

PrintStream

PrintStream可以装饰其它字节输出流,允许将格式化数据写入到字节输出流中,如下示例,将格式化数据写到控制台上;

package io;import java.io.IOException;import java.io.PrintStream;public class IOTest {  public static void main(String[] args) throws IOException {    // 字节输出流    PrintStream ps = System.out;    //输出格式化数据    ps.println("hello");    ps.printf("%5d\n", 101);    ps.write('2');        ps.close();  }}

ObjectInputStream/ObjectOutputStream

可以装饰其它字节输出流,主要用于对象序列化,可以将一个对象以字节流的形式写入/读取到本地文件中,如下例子:

package io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;class Dog implements Serializable {  /**   *   */  private static final long serialVersionUID = -3581113588185842098L;  private int age;  public Dog(int age) {    this.age = age;  }  public int getAge() {    return this.age;  }}public class IOTest {  public static void main(String[] args) throws IOException, ClassNotFoundException {    ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("C:\\object.data"));    ObjectInputStream input = new ObjectInputStream(new FileInputStream("C:\\object.data"));    Dog dog = new Dog(2);    output.writeObject(dog);     output.flush();    Dog obj = (Dog) input.readObject();    System.out.println(obj.getAge());    output.close();    input.close();  }}

SequenceInputStream

把一个或者多个InputStream串行连接起来,第一个流读完,继续读取第二个流,如下例子

package io;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.SequenceInputStream;public class IOTest {  public static void main(String[] args) throws IOException {    // 内存中的字节数组    byte[] bArr = new byte[] { 1, 2, 3 };    byte[] bArr2 = new byte[] { 4, 5, 6 };    // 字节输入流    InputStream is = new ByteArrayInputStream(bArr);    // 字节输入流    InputStream is2 = new ByteArrayInputStream(bArr2);    // 字节输入流,连接以上两个流    SequenceInputStream sis = new SequenceInputStream(is, is2);    byte[] bff = new byte[3];    // 从输入流中读取字节    sis.read(bff, 0, 3);    System.out.println(bff[0] + "," + bff[1] + "," + bff[2]);    // 会从第二个字节流读取数据    sis.read(bff, 0, 3);    System.out.println(bff[0] + "," + bff[1] + "," + bff[2]);    is.close();    is2.close();    sis.close();  }}