InputStream.read()返回int ,且范圍為0到255間int值 ,從輸入流讀取下一個數據字節(jié),它是以字節(jié)為單位來讀的,即每次只讀取一個字節(jié)內容 ,讀取后面三前面補三個字節(jié)的0,這樣讀取出來的結果就永遠為正,且為0到255間的數。如果因已到達流末尾而沒有可用的字節(jié),則返回值-1 。用于進制文件的讀取。
OutputStream.write(int b)將指定的字節(jié)寫入此輸出流。write 的規(guī)定是:向輸出流寫入一個字節(jié)。要寫入的字節(jié)是參數b的八個低位。b 的24個高位將被忽略。此方法能向文件中寫入負數編碼,即可寫入二進制流的文件,如聲音、圖片等文件。
我們再來看看Reader與Writer字符流相應方法: Reader.readReader.read:讀取單個字符。在有可用字符、發(fā)生 I/O 錯誤或者已到達流的末尾前,此方法一直阻塞。范圍在 0 到 65535 之間 (0x00-0xffff),實質上讀取出來的就是一個char型,即為Unicode編碼了。如果已到達流的末尾,則返回 -1
Writer. write(int c)Writer. write(int c):寫入單個字符。要寫入的字符包含在給定整數值的 16 個低位中,16 高位被忽略。
從上面可以看出是兩類字符流,一種是字節(jié)流,另一種是字符流,如果我們讀取/寫入的是一個二進制文件,則使用字節(jié)流InputStream.read/OutputStream.write;如果我們讀取/寫入的是一個字符文件,則使用字符流Reader.read/Writer.write會很方便,當然字符流也可以使用字節(jié)流來操作,只是在某些情況下不是很方便。
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import junit.framework.TestCase; public class TestBinaryStreamReadWrite extends TestCase { /* * 寫二進制文件(如聲音文件)時,只能使用字節(jié)流寫。outputStream.write方法 只寫入最低八位, * 前三字節(jié)會丟棄掉,只存儲最后一字節(jié) */ public void testCreateByteFile() { try { FileOutputStream fo = new FileOutputStream("e:/tmp/tmp"); byte b = -1; //向文件寫兩個-1,沒有編碼為-1的字符,所以創(chuàng)建出的文件為純二進制文件 fo.write(b); fo.write(b); fo.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * InputStream.read方式是讀取一個字節(jié)內容后,以int型返回,在這之間有一個轉換的過程:當讀 * 取一個字節(jié)內容后,會在這八位二進制前再補24位二進制的0,所以最后返回的字節(jié)編碼為正數,永不 * 會為負數,且范圍為0-255間的整數。這樣如果使用read方法讀取二進制文件時,讀出的編碼是整數, * 原本可能為負編碼,最終顯示成了正編碼。為了確保得到正確的原本二進制編碼,在讀取后只能強制轉 * 換成byte型,或使用read(byte b)方式來讀取。 */ public void testReadEncodeError() { try { FileInputStream fi = new FileInputStream("e:/tmp/tmp"); //read方ifc讀取的一個字節(jié)內容,返回0到255范圍內的int字節(jié)值,如果因已到達流 //末尾而沒有可用的字節(jié),則返回值-1 int readInt = fi.read(); //如果已到達文件末尾,則返回-1。雖然的文件中的每個字節(jié)的內容都是-1,但讀出來的不是-1, //所以第二個字節(jié)也能輸出,而不會出現只能讀取第一個字節(jié),第二個字節(jié)讀不出的問題 while (readInt != -1) { //輸入兩個255,但輸入的編碼是錯誤的,應該為-1才對 System.out.println(readInt); //讀下一字節(jié) readInt = fi.read(); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 使用InputStream.read讀取出的編碼如果經過強轉換byte型后,我們就不能再使用 readByte * != -1 來判斷文件流是否結束了,因為如果為二進制文件,讀出的編碼就有 為負的,總之,如果讀取 * 的是二進制文件,就不能直接使用真實編碼與-1比較,只能使用available或通InputStream.read * (byte[] b)方法返回的所讀字節(jié)數來判斷 */ public void testAvailable() { try { File file = new File("e:/tmp/tmp"); FileInputStream fi = new FileInputStream(file); System.out.println("available實質上與file的length相同:" +file.length()); //當使用read方法讀取出的編碼后經強轉byte后,不能使用 (byte) fi.read() != -1 來 //判斷是文件流是否結束,這里我們只能使用available來判斷是否達文件尾 while (fi.available() > 0) { System.out.println("available=" + fi.available()); //使用read()方法讀取字節(jié)內容的編碼后,只能強轉byte型才能得到真實的編碼 System.out.println((byte) fi.read()); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 讀取二進制文件(如圖片)而非字符文件時,除了使用read()讀取強轉byte型,使用 InputStream. * read(byte[] b)是最好的方式,此時使用讀取返回的字節(jié)數來判斷是否讀完 */ public void testReadByByteArr() { try { FileInputStream fi = new FileInputStream("e:/tmp/tmp"); byte[] byteArr = new byte[1024]; //讀取的字節(jié)數 int readCount = fi.read(byteArr); //如果已到達文件末尾,則返回-1 while (readCount != -1) { for (int i = 0; i < readCount; i++) { System.out.println(byteArr[i]); } readCount = fi.read(byteArr); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 使用InputStream.read讀取二進制文件強轉換byte型獲取真實編碼后,不能使用readByte != * -1 來判斷是否到文件尾 */ public void testGetBytecodeByConvernt() { try { FileInputStream fi = new FileInputStream("e:/tmp/tmp"); //讀取的一個字節(jié)內容,強制轉byte型,得到真實的編碼 byte readByte = (byte) fi.read(); //這里我們不能使用如下方式來判斷是否讀流結束,因為編碼內容本身就是-1,所以不會輸出任何內容 while (readByte != -1) { System.out.println((byte) readByte); readByte = (byte) fi.read(); } fi.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } |
|