4. 字節數組流和字符數組流
很多網上的教程在介紹FileInputStream的時候,經常寫出這樣的代碼:
FileInputStream fis = new FileInputStream(outputfile);
byte[] buf = new byte[1024];
int len = fis.read(buf);
代碼中使用1024字節的byte數組來存儲從文件中讀入的字節,但實際工作中文件不一定會小於1024字節,因此這裏需要的是一個可變長的字節數組。但是java中並不支持ArrayList,如果自己編寫動態可擴展的byte數組又比較浪費時間,因此這裏最合適的選擇便是ByteArrayOutputStream。
ByteArrayInputStream和ByteArrayOutputStream是用來表示內存中的字節數組流。其中ByteArrayOutputStream可以用來寫入變長的字節數組,這對於不知道輸入內容的具體長度時非常有用,例如要將一個文件的內容或者網絡上的內容讀入一個字節數組時。
例子代碼:讀入一個未知大小的文件到內存中(假設此文件使用默認編碼)
public static void byteArrayOutputStreamExam() {
try {
FileInputStream fis = new FileInputStream("d:\\d.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf))!=-1){
baos.write(buf,0,len);
}
baos.flush();
byte[] result = baos.toByteArray();
String s = new String(result);
System.out.println(s);
baos.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
例子代碼:將一個byte數組做爲輸入流ByteArrayInputStream的來源,輸入到一個ByteArrayOutputStream中。有趣的是,這段byte數組實際上是一段unicode編碼,代表一些中文字符,程序中最後將byte數組轉換爲unicode編碼的字符,並打印了這些字符。
public static void byteArrayInputStreamExam() {
byte[] buf = new byte[256];
//賦值一段漢字的unicode編碼,從4e00至4eff
for (int i = 0x00; i < 0xff; i = i + 2) {
buf[i] = 0x4e;
buf[i + 1] = (byte) i;
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] getbuf = new byte[128];
int len = 0;
try {
while ((len = byteArrayInputStream.read(getbuf)) != -1) {
byteArrayOutputStream.write(getbuf, 0, len);
}
byte[] result = byteArrayOutputStream.toByteArray();
//將得到的字節轉換爲unicode編碼的字符串
String s = new String(result, "unicode");
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
運行輸出爲:
一丂丄丆丈上丌與丐丒且世丘業東丞丠丟兩並丨個丬丮豐串臨丶丸爲丼舉乀乂乄乆麼乊烏乎樂乒喬乖乘乚乜乞習乢乤書乨乪乬乮買乲乴乶乸乺乼乾亀亂亄了予亊二於亐互五亖亙亞亜亞亠亢交亦亨亪京亮亰親亴亶嚲人亼亾什仂仄僕仈今仌從仐仒仔他付仚仜仞仠仢令仦仨儀們仮仰仲仴件仸仺仼仾
ByteArrayInputStream和ByteArrayOutputStream是字節數組流,那麼與之對應的字符數組流則是StringReader和StringWriter(早期java使用StringBufferInputStream和StringBufferOutputStream,這兩個類在jdk1.1後被廢棄),也給出一個例子:
public static void stringReaderExam() {
String str = "This is a good day.今天是個好天氣。";
StringReader stringReader = new StringReader(str);
StringWriter stringWriter = new StringWriter();
char[] buf = new char[128];
int len = 0;
try {
while ((len = stringReader.read(buf)) != -1) {
stringWriter.write(buf, 0, len);
}
stringWriter.flush();
String result = stringWriter.toString();
System.out.println(result);
stringWriter.close();
stringReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
與字節數組流相比,字符數組流反而用得更少,因爲StringBuilder和StringBuffer也能方便的用來存儲動態長度的字符,而且大家更熟悉這些類。
本系列的其他文章
Java流編程實例之一–Java中的字節與字符
Java流編程實例之二–文件流