本篇将对JAVA I/O流中的字节流InputStream/OutputStream做个简单的概括:
总得来说,每个字节流类都有一个对应的用途,如下:
再看下字节流InputStream/OutputStream的组成结构,如下图;
接下来逐个介绍;
简单地说,就是字节数组与字节输入输出流之间的各种转换,举个例子如下:
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对文件进行写入及读取,如下代码,可以实现文件的复制:
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(); } }
可用于同一个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]); } }); } }
带缓冲区的字节流,装饰器模式在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(); } }
可装饰其它字节流,实现自定义过滤字节流的基类,基本上是简单的覆盖了InputStream/OutputStream中的方法,意义不是很大;
可装饰其它字节输入流,增加的功能是是回退读取,如下例子:
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(); } }
可装饰其它字节输入流,增加从输入流中读取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可以装饰其它字节输出流,允许将格式化数据写入到字节输出流中,如下示例,将格式化数据写到控制台上;
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(); } }
可以装饰其它字节输出流,主要用于对象序列化,可以将一个对象以字节流的形式写入/读取到本地文件中,如下例子:
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(); } }
把一个或者多个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(); } }