在Java中是否有办法向磁盘写入大量的整数?我在Android上执行此操作,并且没有找到任何接近本机C代码的方法。
生成的文件无需可移植到具有不同表示形式的不同计算机,因此逻辑上只需对基础字节进行批量写入就足够了。但我不知道如何从Java中有效地做到这一点。
我试过在网上搜索,并测试了以下内容:
提前致谢
NIO代码:
int[] array = new array[10000000];
...
raf = new RandomAccessFile(ti.testFileName, "rw");
chan = raf.getChannel();
MappedByteBuffer out = chan.map(FileChannel.MapMode.READ_WRITE, 0, array.length*4);
ib = out.asIntBuffer();
ib.put(array);
out.force();
raf.close();
答案 0 :(得分:3)
你说它很慢但速度很可能取决于磁盘子系统的速度。您应该能够在大约半秒内将40 MB写入常规磁盘以提交到磁盘。
以下使用NIO,在工作站上写入时间为665毫秒,时间间隔为62毫秒。读取和写入会使相同数量的数据混乱,但读取可以从OS缓存中获取数据,这与写入磁盘所需的时间不同。
int[] ints = new int[10 * 1000 * 1000];
long start = System.nanoTime();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(ints.length*4+4);
byteBuffer.putInt(ints.length);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(ints);
byteBuffer.position(0);
FileChannel fc = new FileOutputStream("main.dat").getChannel();
fc.write(byteBuffer);
fc.force(false);
fc.close();
long time = System.nanoTime() - start;
System.out.println("Write time " + time / 1000 / 1000 + " ms.");
long start2 = System.nanoTime();
FileChannel fc2 = new FileInputStream("main.dat").getChannel();
ByteBuffer lengthBuffer = ByteBuffer.allocate(4);
while(lengthBuffer.remaining()>0) fc2.read(lengthBuffer);
int length = lengthBuffer.getInt(0);
int[] ints2 = new int[length];
ByteBuffer buffer2 = ByteBuffer.allocateDirect(length*4);
while(buffer2.remaining()>0 && fc2.read(buffer2) > 0);
buffer2.flip();
buffer2.asIntBuffer().get(ints2);
long time2 = System.nanoTime() - start2;
System.out.println("Read time " + time2 / 1000 / 1000 + " ms.");
我已将长度添加到文件的开头,因此不必假设它。顺便说一下:我已经修复了写中的错误。
答案 1 :(得分:1)
我不知道Android的实现,但在标准的Java中,优秀的老式IO通常优于NIO。
例如,如果你有一个字节数组,我相信下面的代码应该相对较快:
byte[] bytes = new byte[10000];
// ...
FileOutputStream out = new FileOutputStream(...);
try {
out.write(bytes);
} finally {
out.close();
}
请记住,这将阻塞,直到写入整个字节数组。但是你没有说明非阻塞行为是否存在问题。
你没有提到的另一件事是你打算在写入文件时对整数进行编码。您需要在写入文件之前在内存中执行编码,但是数组可能太大而无法一次编码所有内容,在这种情况下,您可以使用几百K的块进行编码/写入。
答案 2 :(得分:0)
彼得,
当某些事情看起来好得令人难以置信时,通常情况就是如此。写入40MB数据的89msecs表明你的硬盘带宽要大得多500MB /秒(因为你还包括打开和关闭文件的时间)。这不可能是真的。你检查的文件实际上是40MB大小。另外,我建议您初始化缓冲区以查看文件内容不是全部为零。可能是一个未被触及的缓冲区,只是跳过了。不管它是什么,你拥有的数字太好了,不可能成真。
感谢。
答案 3 :(得分:0)
考虑缓存输出流