OutputStream
這是一個Abstract類,是Lucene自己的一個文件輸出流的基類
BUFFER_SIZE = 1024 緩沖區(qū) 大小為 1024bit
bufferStart = 0 文件位置指針
bufferPosition = 0 內(nèi)存緩沖區(qū)指針
public final void writeByte(byte b) throws IOException {
if (bufferPosition >= BUFFER_SIZE)
flush();
buffer[bufferPosition++] = b;
}
幾乎所有的寫入函數(shù)都要調(diào)用這個函數(shù),如果緩沖區(qū)的當前容量已經(jīng)等于他的最大容量,則將緩沖區(qū)中的數(shù)據(jù)寫入文件。
public final void writeBytes(byte[] b, int length) throws IOException
批量寫byte進入內(nèi)存緩沖
public final void writeInt(int i) throws IOException
寫入整形數(shù)據(jù)
public final void writeLong(long i) throws IOException
寫入長整型數(shù)據(jù),即結(jié)合移位運算調(diào)用兩次writeInt(int i)
另外,最值得注意的是在該類中有兩個最特殊的函數(shù)
writeVInt(int i) / writeVLong(long i),
先說
writeVInt(int i ) {
while ((i & ~0x7F) != 0) {
writeByte((byte)((i & 0x7f) | 0x80));
i >>>= 7;
}
writeByte((byte)i);
}
~0x7F==~(0111 1111)==(1000 0000)==0x80
((i & ~0x7F) != 0) 這一句判斷i是否大于0x80,如果不是則說明該int只有一個字節(jié)的有效數(shù)據(jù),其他字節(jié)都是0,直接轉(zhuǎn)化為Byte寫入。
如果大于0x80則
(i & 0x7f) | 0x80
i&0x7f 只對后7位進行處理,|0x80將第8位置1,與前面的7個bit構(gòu)成一個字節(jié),置1的原因是說明該字節(jié)并不是一個完整的整形數(shù),需要與其他的字節(jié)合起來才能構(gòu)成一個整形數(shù)字。
這個算法相當于將一個32bit的整形數(shù)字按照每7位編碼成一個字節(jié)進行存儲,將按照整形數(shù)的大小存儲1-5個字節(jié)。
writeVLong(long i)方法大致與其相同。
final void writeChars(String s, int start, int length)
將字符串轉(zhuǎn)化成UTF-8編碼的格式進行存儲。
附:
UNICODE值 UTF-8編碼
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
可見對于在 0x00-0x7F范圍內(nèi)的UNICODE值(最大有效數(shù)位:7位),將會編碼成單字節(jié)的,會大大節(jié)約存儲空間。
對于在 0x80-0x7FF范圍內(nèi)的UNICODE(最大有效數(shù)位:11位),會編碼成雙字節(jié)的。先存儲原字節(jié)低5位的數(shù)位,且將最高位和次高位都置1,再次高位置0(writeByte((byte)(0xC0 | (code >> 6)));)。然后存儲后6位的字節(jié),將前兩位置10(writeByte((byte)(0x80 | (code & 0x3F)));)
對于其他的UNICODE值則
writeByte((byte)(0xE0 | (code >>> 12))); 4位
writeByte((byte)(0x80 | ((code >> 6) & 0x3F))); 5位
writeByte((byte)(0x80 | (code & 0x3F))); 3- 5位
final void writeString(String s) throws IOException
該函數(shù)首先用s.length()判斷該String總共有多少個字符
然后首先調(diào)用writeVInt寫入這個字符長度
再調(diào)用writeChars(s,s.length())寫入字符
在inputStream中的readString()方法則與其相反,首先用readVInt()方法讀取字符長度len 然后讀取len長度的字符
protected final void flush() throws IOException
該方法調(diào)用另外一個方法flushBuffer將緩沖區(qū)中的數(shù)據(jù)輸出,然后清空緩沖區(qū);
abstract void flushBuffer(byte[] b, int len) throws IOException
可見flushBuffer方法是abstract的,即需要其子類對該方法進行覆寫,以定位該輸出流的輸出方式。
final long getFilePointer() throws IOException
得到文件指針的位置,即得到輸出流已經(jīng)輸出的字節(jié)數(shù)。
public void seek(long pos) throws IOException
輸出緩沖區(qū)的內(nèi)容,然后將文件指針定位到long所指示的文件位置。
abstract long length() throws IOException
返回文件中已有的字節(jié)數(shù)。需要子類實現(xiàn)。