tim*_*mbo 8 java nio disk unc drive
我正在使用一个使用Java NIO的库,以便直接将文件映射到内存,但我无法直接读取磁盘.
我可以直接使用FileInputStreamUNC 读取磁盘,例如
File disk = new File("\\\\.\\PhysicalDrive0\\");
try (FileInputStream fis = new FileInputStream(disk);
BufferedInputStream bis = new BufferedInputStream(fis)) {
byte[] somebytes = new byte[10];
bis.read(somebytes);
} catch (Exception ex) {
System.out.println("Oh bother");
}
Run Code Online (Sandbox Code Playgroud)
但是,我无法将其扩展到NIO:
File disk = new File("\\\\.\\PhysicalDrive0\\");
Path path = disk.toPath();
try (FileChannel fc = FileChannel.open(path, StandardOpenOption.READ)){
System.out.println("No exceptions! Yay!");
} catch (Exception ex) {
System.out.println("Oh bother");
}
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪(由原因决定)是:
java.nio.file.FileSystemException: \\.\PhysicalDrive0\: The parameter is incorrect.
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.newFileChannel(WindowsFileSystemProvider.java:115)
at java.nio.channels.FileChannel.open(FileChannel.java:287)
at java.nio.channels.FileChannel.open(FileChannel.java:334)
at hdreader.HDReader.testcode(HDReader.java:147)
Run Code Online (Sandbox Code Playgroud)
我找不到解决方案,但我看到了如何从java访问磁盘上的特定原始数据.Daniel Alder的回答建议使用GLOBALROOT似乎是相关的,因为答案在答案中使用了FileChannel,但我似乎无法使用这种模式找到驱动器.有没有办法列出GLOBALROOT下的所有设备或类似的东西?
目前我正在考虑用直接替换NIO的使用InputStream,但是如果可以的话我想避免这种情况.首先,使用NIO是有原因的,其次,它运行了大量代码,需要大量工作.最后,我想知道如何实现Daniel的解决方案,以便我可以在将来写入设备或使用NIO.
总结一下:如何直接使用Java NIO(而不是InputStreams)访问驱动器,和/或是否有办法列出可通过GLOBALROOT访问的所有设备,以便我可以使用Daniel Alser的解决方案?
答案摘要: 我保留了过去的编辑(下面)以避免混淆.在EJP和Apangin的帮助下,我认为我有一个可行的解决方案.就像是
private void rafMethod(long posn) {
ByteBuffer buffer = ByteBuffer.allocate(512);
buffer.rewind();
try (RandomAccessFile raf = new RandomAccessFile(disk.getPath(), "r");
SeekableByteChannel sbc = raf.getChannel()) {
sbc.read(buffer);
} catch (Exception ex) {
System.out.println("Oh bother: " + ex);
ex.printStackTrace();
}
return buffer;
}
Run Code Online (Sandbox Code Playgroud)
只要posn参数是扇区大小的倍数(在这种情况下设置为512),这将起作用.请注意,这也适用于Channels.newChannel(FileInputStream),在这种情况下似乎总是返回一个SeekableByteStream,并且看起来将它转换为一个是安全的.
从快速和肮脏的测试看来,这些方法似乎真正寻求并且不仅仅是跳过.我在驱动器开始时搜索了一千个位置,然后读取它们.我做了同样的事情,但增加了一半磁盘大小的偏移量(搜索磁盘背面).我发现:
这向我表明,这是真正的追求,而不仅仅是阅读和跳过(如流程所趋).在这个阶段速度仍然很糟糕,它使我的硬盘听起来像一台洗衣机,但代码是为快速测试而设计的,并且尚未变得漂亮.它仍然可以正常工作.
感谢EJP和Apangin的帮助.阅读他们各自的答案.
编辑: 我已经在Windows 7机器上运行我的代码(我最初没有),我得到一个稍微不同的异常(见下文).这是使用管理员权限运行的,第一段代码仍可在相同条件下运行.
java.nio.file.FileSystemException: \\.\PhysicalDrive0\: A device attached to the system is not functioning.
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.newFileChannel(WindowsFileSystemProvider.java:115)
at java.nio.channels.FileChannel.open(FileChannel.java:287)
at java.nio.channels.FileChannel.open(FileChannel.java:335)
at testapp.TestApp.doStuff(TestApp.java:30)
at testapp.TestApp.main(TestApp.java:24)
Run Code Online (Sandbox Code Playgroud)
编辑2: 为了回应EJP,我尝试过:
byte[] bytes = new byte[20];
ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.rewind();
File disk = new File("\\\\.\\PhysicalDrive0\\");
try (FileInputStream fis = new FileInputStream(disk);
ReadableByteChannel rbc = Channels.newChannel(new FileInputStream(disk))) {
System.out.println("Channel created");
int read = rbc.read(bb);
System.out.println("Read " + read + " bytes");
System.out.println("No exceptions! Yay!");
} catch (Exception ex) {
System.out.println("Oh bother: " + ex);
}
Run Code Online (Sandbox Code Playgroud)
当我尝试这个时,我得到以下输出:
创建频道
哦麻烦:java.io.IOException:参数不正确
所以看来我可以创建一个FileChannel或ReadableByteChannel,但我不能使用它; 也就是说,错误只是推迟了.
当访问没有缓冲的物理驱动器时,您只能读取完整的扇区。这意味着,如果扇区大小为 512 字节,则只能读取 512 字节的倍数。将缓冲区长度更改为 512 或 4096(无论您的扇区大小是多少)并且FileChannel可以正常工作:
ByteBuffer buf = ByteBuffer.allocate(512);
try (RandomAccessFile raf = new RandomAccessFile("\\\\.\\PhysicalDrive0", "r");
FileChannel fc = raf.getChannel()) {
fc.read(buf);
System.out.println("It worked! Read bytes: " + buf.position());
} catch (Exception e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
请参阅对齐和文件访问要求。
您的原始FileInputStream代码显然可以工作,因为BufferedInputStream它的默认缓冲区大小为 8192。将其拿走 - 代码将因相同的异常而失败。
| 归档时间: |
|
| 查看次数: |
1898 次 |
| 最近记录: |