我正在修改H2 MVStore 1.4.191的源代码,通过做一些线程休眠来写文件。 最大的变化是文件不再在一次写入,而是由2 ^ 16个字节的块组成。 MVStore使用java nio FileChannel和ByteBuffer来编写其文件。问题是结果与原始版本不同。似乎FileChannel添加了空格字符(ASCII中的0x20),比如连续超过40个。或者它可能没有删除这个空格,与原始版本相反,我不知道。
我认为这是由于文件写作。 方法file.write(buffer,position),其中file是FileChannel对象,并返回写入的字节数,有时返回的数字小于缓冲区大小,在原始版本的H2中。在我的版本中,它永远不会发生。
有关于ByteBuffer,FileChannel和我的问题的提示吗?
答案 0 :(得分:0)
原始代码调用写入函数几次(它写入页眉,页脚和数据)
int off = 0;
do {
int len = file.write(src, pos + off);
off += len;
} while (src.remaining() > 0);
src是ByteBuffer,文件是sun.io的FileChannelImpl。缓冲区可以包含超过50MB的数据。
通过这段代码,我开发了一个解决方案,通过在每个缓冲区之间添加睡眠功能,将ByteBuffer分成2 ^ 16大小的缓冲区:
int off = 0;
byte[] buffer = src.array();
int size = src.array().length;
int chunkSize = 128;
List<byte[]> splittedBuffer = new ArrayList<byte[]>();
int i = 0;
while (i < size) {
int start = i;
int end = i + chunkSize;
if (end > size)
{
//if buffer size is not a multiple of 2^16, the last
//chunk will be smaller
end = size;
}
splittedBuffer.add(Arrays.copyOfRange(src.array(), start, end));
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i += chunkSize;
}
int offset = 0;
for (byte[] chunk : splittedBuffer) {
int len=file.write(ByteBuffer.wrap(chunk),pos+offset);
offset+=len;
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
最后,问题可能不是添加了空格,而是一部分数据写在错误的地方。我要检查一下。
答案 1 :(得分:0)
确定,
问题是我使用ByteBuffer的大小来分割它而不是它的更小的限制(在过程中由H2设置)
感谢您的帮助
此致