本篇將對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(); } }