我想在不使用本机库的情况下通过 Java 从磁盘中恢复文件
我正在使用 Java 8 执行此操作
据我所知,删除的文件会保留在磁盘上,直到它们被覆盖
我可以直接访问 linux 上的磁盘并且可以读取原始数据,但是,例如,如何解析 ext4 或 NTFS 文件系统上的已删除文件?
谢谢。
我想在不使用本机库的情况下通过 Java 从磁盘中恢复文件
我正在使用 Java 8 执行此操作
据我所知,删除的文件会保留在磁盘上,直到它们被覆盖
我可以直接访问 linux 上的磁盘并且可以读取原始数据,但是,例如,如何解析 ext4 或 NTFS 文件系统上的已删除文件?
谢谢。
恢复已删除的文件需要了解底层文件系统是如何实现的,因此您需要先阅读一些内容才能到达任何地方。
理论上,是的,你绝对可以在纯 Java 中做到这一点;您只需要了解如何绕过文件系统从原始磁盘读取数据。在 Unix 系统上,这很简单:将设备节点作为文件打开(您需要root
权限)然后读取。在 Windows 上可能有类似的过程;在最坏的情况下,您必须在 C 或 C++ 中创建一个帮助程序库来为您读取数据。
访问原始数据后,查找文件在特定文件系统中的存储方式,并开始在您读取的数据中寻找类似的模式。
不过,这不是你可以在一个下午做的事情。
更新:如何绕过文件系统。
在 Unix 系统上,您可以像这样从分区或卷中读取:
InputStream sda1 = new FileInputStream("/dev/sda1");
int firstByte = sda1.read();
在 Windows 上,您将从 \\.\PhysicalDisk0
. 从命名文件、路径和命名空间:
使用 Win32 设备命名空间的另一个示例是使用
CreateFile
带有“\\.\PhysicalDiskX”(其中 X 是有效整数值)或“\\.\CdRomX”的函数。这允许您绕过文件系统直接访问这些设备。这是因为这些设备名称是由系统在枚举这些设备时创建的,并且一些驱动程序还会在系统中创建其他别名。例如,实现名称“C:\”的设备驱动程序有自己的命名空间,它也恰好是文件系统。通过该
CreateFile
函数的 API 通常使用“\\.\”前缀,因为CreateFile
该函数用于打开文件和设备,具体取决于您使用的参数。如果您正在使用 Windows API 函数,您应该使用“\\.\”前缀来仅访问设备而不是文件。
大多数 API 不支持 "\\.\"; 只有那些设计用于设备名称空间的人才能识别它。请务必检查每个 API 的参考主题。
我不知道 Java API 是否是使用实现的,CreateFile
或者它是否进行了一些名称修改,这意味着您无法访问设备名称空间。在最坏的情况下,您必须创建一个包装库来调用CreateFile
并将它返回的 HANDLE 转换为可以在 Java 中使用的文件描述符;这根本不是工作。
根据定义,文件是存储在永久存储设备上的命名字节序列。文件由名为文件系统的操作系统组件管理。文件系统使用术语“文件”进行操作,并将该术语转换为较低级别的术语,如卷、扇区、块等。
文件名(和路径)与磁盘上实际存储信息的块之间的映射称为文件表,并由文件系统管理。
当您删除文件时,您要求文件系统从文件表中删除适当的条目。这意味着文件内容实际上并没有从磁盘中删除,如果你足够幸运,可能可以恢复。为什么可能?因为一旦从表中删除文件条目,文件占用的空间就可以重新使用,因此其他信息可以存储在那里。
有一些工具可以尝试恢复信息。这些工具在文件系统下工作,即使用较低级别的 API。可能他们正在直接与司机交谈。Java 不提供执行此操作的 API。
因此,您有以下解决方案。