From Gossip@Openhome

Java Gossip: PushbackInputStream

PushbackInputStream擁有一個PushBack緩衝區,您從這個物件讀出資料後,如果願意的話,只要PushBack緩衝區沒有滿,就可以使用unread()將資料回推回串流的前端。

舉個使用PushbackInputStream的例子,假設一個文字檔案中同時儲存有ASCII碼與BIG5中文字,您希望判斷出那些位置是 ASCII而那些位置是BIG5中文字的位置,BIG5中文字使用兩個位元組來表示,而ASCII只使用一個。

BIG5中文為了與ASCII相容,採第一個位元組範圍為0xA4至0xF9,而第二個位元組為0x40到0x7E以及0xA1至0xFE,所以讀取時只要先讀到位元組是在0xA4至0xF9,就表示它可能是一個中文字的前半。

為了說明PushbackInputStream的功能,您的範例則是一次從檔案中讀取兩個位元組,並檢查其是否在0xA440與 0xFFFF之間,以簡單的判斷其是否為BIG5碼,如果不在這個範圍之內,則可能是個ASCII範圍內的字元,您顯示它,並將讀出的第二個位元組推回串 流,以待下一次可以重新讀取

  • PushbackStreamDemo.java
package onlyfun.caterpillar;

import java.io.*;

public class PushbackStreamDemo {
public static void main(String[] args) {
try {
PushbackInputStream pushbackInputStream =
new PushbackInputStream(
new FileInputStream(args[0]));
byte[] array = new byte[2];
int tmp = 0;
int count = 0;

while((count = pushbackInputStream.read(array))
!= -1) {
// 兩個位元組轉換為整數
tmp = (short)((array[0] << 8) |
(array[1] & 0xff));
tmp = tmp & 0xFFFF;

// 判斷是否為BIG5,如果是則顯示BIG5中文字
if(tmp >= 0xA440 && tmp < 0xFFFF) {
System.out.println("BIG5: " + new String(array));
}
else {
// 將第二個位元組推回串流
pushbackInputStream.unread(array, 1, 1);
// 顯示ASCII範圍的字元
System.out.println("ASCII: " +
(char)array[0]);
}
}

pushbackInputStream.close();
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("請指定檔案名稱");
}
catch(IOException e) {
e.printStackTrace();
}
}
}

假設我們的文字檔案中有以下的文字:"這T是e一s個t測試"

執行結果會是:
 BIG5: 這
ASCII: T
BIG5: 是
ASCII: e
BIG5: 一
ASCII: s
BIG5: 個
ASCII: t
BIG5: 測
BIG5: 試