我可以使用 Java 读取/写入 Linux 块设备java.nio
。以下代码有效:
Path fp = FileSystems.getDefault().getPath("/dev", "sdb");
FileChannel fc = null;
try {
fc = FileChannel.open(fp, EnumSet.of(StandardOpenOption.READ, StandardOpenOption.WRITE));
} catch (Exception e) {
System.out.println("Error opening file: " + e.getMessage());
}
ByteBuffer buf = ByteBuffer.allocate(50);
try {
if(fc != null)
fc.write(buf);
} catch (Exception e) {
System.out.println("Error writing to file: " + e.getMessage());
}
但是,内存映射不起作用。下面的代码fails:
MappedByteBuffer mbb = null;
try {
mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 100);
} catch (IOException e) {
System.out.println("Error mapping file: " + e.getMessage());
}
这会失败并出现错误:
java.io.IOException: Invalid argument
at sun.nio.ch.FileDispatcherImpl.truncate0(Native Method)
at sun.nio.ch.FileDispatcherImpl.truncate(FileDispatcherImpl.java:79)
at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:817)
有解决办法吗?也许通过使用不同的库?我在某处读到也许通过使用 JNI 我可以做到这一点,但我找不到任何来源。
根据文档 http://docs.oracle.com/javase/6/docs/api/java/nio/channels/FileChannel.html#map%28java.nio.channels.FileChannel.MapMode,%20long,%20long%29实际映射文件的机制留给实现。看来该实现正在尝试截断文件(可能是因为块设备大小与您指定的大小不同?)。
我很好奇为什么你直接从块设备读取(除非你试图编写某种文件系统实用程序或需要执行原始 I/O 的东西)。如果您需要直接从块设备中读取内存映射文件,您可能需要编写一些 C/C++ 代码来映射文件并处理对其的读/写,并使用 Java/JNI 桥接类来桥接对您的文件的调用。 C/C++ 代码。这样您就可以自己处理调用 mmap() 并可以指定您需要的任何选项。看着mmap() 文档 http://man7.org/linux/man-pages/man2/mmap.2.html你可能无法在你的平台上指定块设备(我猜是Linux,但我可能是错的)。
如果您绝对需要在 Java 中执行此操作,您可能需要执行适当长度和偏移量的 read() 调用和 write() 调用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)