在之前的源代码分析中我们经常遇到神秘的 OutMessage 类的实例,并调用它的 writeInt,query 等方法与 MongoDB 数据库进行交互。
但 OutMessage 继承了 BSONEncoder 类,而 BSONEncoder 的 writeInt 等方法实际上是委托给 OutputBuffer 类的实例执行的。
因此为了弄清楚 OutMessage 类的实例的行为,我们需要先了解 OutputBuffer 类的主要逻辑。
BasicOutputBuffer 和 PoolOutputBuffer 的 write 和 pipe 方法的实现
OutputBuffer 类是一个抽象类,有两个子类: BasicOutputBuffer 和 PoolOutputBuffer。
OutputBuffer 的作用是缓冲对将要写入到输出流中的数据进行缓冲,准备好后通过 pipe 方法将数据输出到输出流中。
子类主要实现了抽象方法 write 和 pipe:
public abstract void write(byte[] b, int off, int len);
public abstract void write(int b);
public abstract int pipe( OutputStream out );
BasicOutputBuffer 类的 write 方法的实现如下:
// 写入数据到缓冲区
public void write(byte[] b, int off, int len){
// 保证缓冲区空间足够
// 不够则开辟新的空间
_ensure( len );
// 复制数据到缓冲区
System.arraycopy( b , off , _buffer , _cur , len );
// 改变代表偏移量和缓冲区大小的数字
_cur += len;
_size = Math.max( _cur , _size );
}
// 保证缓冲区空间足够
// 不够则开辟新的空间
void _ensure( int more ){
// 计算需要的大小
final int need = _cur + more;
// 目前的缓冲区大小足够。
// 不再开辟新的空间
if ( need < _buffer.length )
return;
// 新的缓冲区大小是原来的两倍
int newSize = _buffer.length*2;
// 如果仍然不够,开辟更大的空间
if ( newSize <= need )
newSize = need + 128;
// 创建数组
byte[] n = new byte[newSize];
// 将缓冲区中数据复制到数组中
System.arraycopy( _buffer , 0 , n , 0 , _size );
// 以新的数组作为缓冲区
_buffer = n;
}
// 只写入一个字节
public void write(int b){
// 保证有一个字节的空间
_ensure(1);
// 将 int 型数据的低 8 位保存到缓冲区
_buffer[_cur++] = (byte)(0xFF&b);
// 修改表示缓冲区数据大小的数值
_size = Math.max( _cur , _size );
}
BasicOutputBuffer 类的 pipe 方法的实现如下:
public int pipe( OutputStream out )
throws IOException {
// 将缓冲区中的数据写入输出流中
out.write( _buffer , 0 , _size );
// 返回缓冲区大小
return _size;
}
PoolOutputBuffer 类的 write 方法实现如下:
public void write(byte[] b, int off, int len){
while ( len > 0 ){
// 获取一块当前缓冲区空间
byte[] bs = _cur();
// 计算本次写入大小
int space = Math.min( bs.length - _cur.y , len );
// 将数据复制缓冲区
System.arraycopy( b , off , bs , _cur.y , space );
// 修改偏移量等后续工作
_cur.inc( space );
len -= space;
off += space;
// 其他后续处理
// 如缓冲区满时,创建下一个缓冲区块等
_afterWrite();
}
}
// 只写入一个字节
public void write(int b){
// 获取缓冲区空间
byte[] bs = _cur();
// 将 int 型数值的低 8 为保存到缓冲区
bs[_cur.getAndInc()] = (byte)(b&0xFF);
// 后续处理
_afterWrite();
}
PoolOutputBuffer 类的 pipe 方法实现如下:
public int pipe( OutputStream out )
throws IOException {
if ( out == null )
throw new NullPointerException( "out is null" );
int total = 0;
for ( int i=-1; i<_fromPool.size(); i++ ){
// 获取对象池中指定索引的数据
byte[] b = _get( i );
// 获取对象池中指定索引的数据的大小
int amt = _end.len( i );
// 将数据写入到输出流中
out.write( b , 0 , amt );
// 增加表示总数据大小的数值
total += amt;
}
return total;
}
OutputBuffer 类的 write* 方法
基于子类实现的 write 方法,OutputBuffer 实现了一系列 write* 方法
// 写入 int 型
public void writeInt( int x ){
// 写入第 1 个字节(第 1 - 8 位)
write( x >> 0 );
// 写入第 2 个字节(第 9 - 16 位)
write( x >> 8 );
// 写入第 3 个字节(第 17 - 24 位)
write( x >> 16 );
// 写入第 4 个字节(第 25 - 32 位)
write( x >> 24 );
}
// 按“大端”(Big End) 法 写入 int 型
public void writeIntBE( int x ){
// 写入第 4 个字节(第 25 - 32 位)
write( x >> 24 );
// 写入第 3 个字节(第 17 - 24 位)
write( x >> 16 );
// 写入第 2 个字节(第 9 - 16 位)
write( x >> 8 );
// 写入第 1 个字节(第 1 - 8 位)
write( x );
}
// 指定位置写入 int 型数据
public void writeInt( int pos , int x ){
// 获取当前位置
final int save = getPosition();
// 设置当前位置
setPosition( pos );
// 写入 int 型数据
writeInt( x );
// 恢复当前位置
setPosition( save );
}
// 写入 long 型数值
public void writeLong( long x ){
// 写入第 1 个字节(第 1 - 8 位)
write( (byte)(0xFFL & ( x >> 0 ) ) );
// 写入第 2 个字节(第 9 - 16 位)
write( (byte)(0xFFL & ( x >> 8 ) ) );
// 写入第 3 个字节(第 17 - 24 位)
write( (byte)(0xFFL & ( x >> 16 ) ) );
// 写入第 4 个字节(第 25 - 32 位)
write( (byte)(0xFFL & ( x >> 24 ) ) );
// 写入第 5 个字节(第 33 - 40 位)
write( (byte)(0xFFL & ( x >> 32 ) ) );
// 写入第 6 个字节(第 41 - 48 位)
write( (byte)(0xFFL & ( x >> 40 ) ) );
// 写入第 7 个字节(第 49 - 56 位)
write( (byte)(0xFFL & ( x >> 48 ) ) );
// 写入第 8 个字节(第 57 - 64 位)
write( (byte)(0xFFL & ( x >> 56 ) ) );
}
// 写入 double 型数值
public void writeDouble( double x ){
// 将 double 型转为 long 型 (IEEE 754 表示法) 后写入
writeLong( Double.doubleToRawLongBits( x ) );
}
分享到:
相关推荐
MongoDB Java Driver 简单操作
mongoDB java driver api mongoDB java 驱动 所有类的api
NULL 博文链接:https://xxing22657-yahoo-com-cn.iteye.com/blog/1233940
标签:mongodb、driver、core、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
mongodb java Driver,具体使用请看我的博客:http://blog.csdn.net/lablenet
mongodb driver java 源码 2.5.3 版本
标签:mongodb、driver、sync、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请...
java和mongodb连接,需要mongodb-driver,您还必须下载其依赖项: bson和 mongodb-driver-core》》3个包: mongodb-driver-3.8.2.jar; bson-3.8.2.jar; mongodb-driver-core-3.8.2.jar
标签:mongodb、driver、sync、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,...
mongodb-java-driver-4.4.0.jar
标签:mongodb、driver、core、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,...
MongoDB Java操作大全 源代码 实例
mongodb-async-driver-2.0.1 jar包
MongoDBjava各版本驱动下载
mongodb c#驱动 最新驱动mongodb.driver.dll 版本2.12.0-beta1,包内有MongoDB.Bson.dll 、mongodb.driver.core.dll 等文件
mongodb 的java驱动,最新版本编译,有需要的同学拿去。
MongoDBjava驱动源码程序,适合大神们研究学习。
亲测可用,解压包含三个jar包,引用时sources和doc包根据需要添加。 mongo-java-driver-3.5.0.jar; mongo-java-driver-3.5.0-javadoc.jar; mongo-java-driver-3.5.0-sources.jar;
mongodb-driver-core-3.4.3,mongodb java开发常用组件。
mongodb数据库的java使用的驱动程序,版本为2.11。 mongodb数据库是现在比较流行的文件数据库。具体就不多说了。 包含了source包,方便调试。