Java 按位讀取寫入檔案
阿新 • • 發佈:2019-02-04
在實現Huffman樹時,壓縮和解壓需要從檔案中按位讀取,即一次只讀一個位或者寫一個位。
《演算法(第四版)》中提供了一種實現方法,StdIn類和StdOut類,豁然開朗。
按位讀取
方法:
1. 開闢一個緩衝區int buffer
,用於儲存位,並記錄緩衝區中bit數n
2. 緩衝區不為空時,進行位運算buffer>>(n-1)
,即為buffer中的最高位,實現讀取一個位的操作
例:
buffer(二進位制表示) | 11001010 |
---|---|
n | 8 |
buffer向右移7個位buffer >> (8-1)
,即可得到最高位1
public static boolean readBoolean() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
n--;
boolean bit = ((buffer >> n) & 1) == 1;
if (n == 0) fillBuffer();
return bit;
}
其他部分實現
public final class BinaryStdIn {
private static BufferedInputStream in = new BufferedInputStream(System.in);
private static final int EOF = -1; // end of file
private static int buffer; // one character buffer
private static int n; // number of bits left in buffer
// static initializer
static {
fillBuffer();
}
// don't instantiate
private BinaryStdIn() { }
private static void fillBuffer() {
try {
buffer = in.read();
n = 8;
}
catch (IOException e) {
System.out.println("EOF");
buffer = EOF;
n = -1;
}
}
/**
* Returns true if standard input is empty.
* @return true if and only if standard input is empty
*/
public static boolean isEmpty() {
return buffer == EOF;
}
}
按位寫入
按位寫入的實現,主要是利用與運算|
的特性:
1. 0 | n = n
2. 1 | n = 1
與按位讀取相同,我們同樣要使用一個緩衝區。
假設要寫入的位為 bit,則
1. 將buffer左移一位buffer <<= 1
,空出一位存放bit
2. 如果bit為1,則 buffer = buffer | 1;如果bit為0,則buffer即為寫入bit後的緩衝區
例如:
buffer(二進位制表示) | 110110 |
---|---|
bit | 1 |
buffer <<= 1 | 1101100 |
bit的8位二進位制表示 | 00000001 |
與運算結果 | 1101101 |
程式碼實現
private static void writeBit(boolean bit) {
// add bit to buffer
buffer <<= 1;
if (bit) buffer |= 1;
// if buffer is full (8 bits), write out as a single byte
n++;
if (n == 8) clearBuffer();
}
完整實現
public final class BinaryStdOut {
private static BufferedOutputStream out = new BufferedOutputStream(System.out);
private static int buffer; // 8-bit buffer of bits to write out
private static int n; // number of bits remaining in buffer
// don't instantiate
private BinaryStdOut() { }
/**
* Write the specified bit to standard output.
*/
private static void writeBit(boolean bit) {
// add bit to buffer
buffer <<= 1;
if (bit) buffer |= 1;
// if buffer is full (8 bits), write out as a single byte
n++;
if (n == 8) clearBuffer();
}
private static void clearBuffer() {
if (n == 0) return;
if (n > 0) buffer <<= (8 - n);
try {
out.write(buffer);
}
catch (IOException e) {
e.printStackTrace();
}
n = 0;
buffer = 0;
}