OutputStream
这是一个Abstract类,是Lucene自己的一个文件输出流的基类
BUFFER_SIZE = 1024 缓冲区 大小为 1024bit
bufferStart = 0 文件位置指针
bufferPosition = 0 内存缓冲区指针
public final void writeByte(byte b) throws IOException {
if (bufferPosition >= BUFFER_SIZE)
flush();
buffer[bufferPosition++] = b;
}
几乎所有的写入函数都要调用这个函数,如果缓冲区的当前容量已经等于他的最大容量,则将缓冲区中的数据写入文件。
public final void writeBytes(byte[] b, int length) throws IOException
批量写byte进入内存缓冲
public final void writeInt(int i) throws IOException
写入整形数据
public final void writeLong(long i) throws IOException
写入长整型数据,即结合移位运算调用两次writeInt(int i)
另外,最值得注意的是在该类中有两个最特殊的函数
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只有一个字节的有效数据,其他字节都是0,直接转化为Byte写入。
如果大于0x80则
(i & 0x7f) | 0x80
i&0x7f 只对后7位进行处理,|0x80将第8位置1,与前面的7个bit构成一个字节,置1的原因是说明该字节并不是一个完整的整形数,需要与其他的字节合起来才能构成一个整形数字。
这个算法相当于将一个32bit的整形数字按照每7位编码成一个字节进行存储,将按照整形数的大小存储1-5个字节。
writeVLong(long i)方法大致与其相同。
final void writeChars(String s, int start, int length)
将字符串转化成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范围内的UNICODE值(最大有效数位:7位),将会编码成单字节的,会大大节约存储空间。
对于在 0x80-0x7FF范围内的UNICODE(最大有效数位:11位),会编码成双字节的。先存储原字节低5位的数位,且将最高位和次高位都置1,再次高位置0(writeByte((byte)(0xC0 | (code >> 6)));)。然后存储后6位的字节,将前两位置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
该函数首先用s.length()判断该String总共有多少个字符
然后首先调用writeVInt写入这个字符长度
再调用writeChars(s,s.length())写入字符
在inputStream中的readString()方法则与其相反,首先用readVInt()方法读取字符长度len 然后读取len长度的字符
protected final void flush() throws IOException
该方法调用另外一个方法flushBuffer将缓冲区中的数据输出,然后清空缓冲区;
abstract void flushBuffer(byte[] b, int len) throws IOException
可见flushBuffer方法是abstract的,即需要其子类对该方法进行覆写,以定位该输出流的输出方式。
final long getFilePointer() throws IOException
得到文件指针的位置,即得到输出流已经输出的字节数。
public void seek(long pos) throws IOException
输出缓冲区的内容,然后将文件指针定位到long所指示的文件位置。
abstract long length() throws IOException
返回文件中已有的字节数。需要子类实现。