是否可以创建java RAM磁盘以与java.io. * API一起使用?

时间:2010-12-13 11:13:26

标签: java unit-testing ramdisk

我正在使用第三方库,它基本上创建了一个输出目录,其中包含不同类型的文件和子目录。我希望能够编写单元测试来确认输出是否正确。

我希望能够将lib与RAM磁盘一起使用,这样磁带库就不会以任何方式触及实际的磁盘板。我的想法是让测试运行和清理非常快(丢弃RAM磁盘?)。

我可以使用的两个最突出的选项是Commons VFSJSR 203。前者对我没用,因为我希望使用java.io. * API而不是Commons VFS类透明地工作。后者没有削减它因为我必须使用JDK 6(它应该是JDK 7的一部分)而且我不知道它是否能与java.io. *无缝地工作(我不会打赌吧。

还有other解决方案,但我不能使用它们的原因与我不能使用Commons VFS相同。由于所涉及的库的复杂性,模拟是不可能的。

在我的linux机器上,我可以轻松地创建一个RAM驱动器并使用java.io. * API,就像我对磁盘上的文件一样。问题是,我希望它是跨平台的,更具体地说,是让磁盘设置成为测试程序的一部分,而不是外部的东西。

那么,有没有办法在Java中注册一个可以与标准java.io. * API一起使用的RAM驱动器?

3 个答案:

答案 0 :(得分:6)

  

那么,有没有办法在Java中注册一个可以与标准java.io. * API一起使用的RAM驱动器?

不使用Java 6或更早版本的JVM。 Java 6及更早版本不提供用于注册文件系统或文件系统类型的任何SPI。因此,要实现一个应用程序将像普通FS一样使用的RAM FS,将需要修改许多java.io.*类的行为。

我认为您可以做的最好的事情是使用主机操作系统实现的RAM FS。您应该能够从Java访问它,就像它是一个普通的文件系统一样。但是,I / O 需要系统调用,因此它不会像RAM文件系统保存在JVM管理内存中那么快。

答案 1 :(得分:4)

理论上斯蒂芬是对的。 但我可以建议你一招。您可以实现自己的FileInputStream和FileOutputStream并将它们放入bootclasspath。您的实现将例如实现open(),read()和readBytes()(这是常规FileInputStream中的本机方法。)

这是针对您的问题的纯java解决方案。它的缺点是你必须在单独的JVM实例中运行测试。

答案 2 :(得分:1)

您要克服的基本问题是原始的java.io API根本不灵活(它们都是指具体的类)。您可以将不同功能放在例如java.io.File中的唯一方法是扩展基类。

在设计类之后扩展类可能是糟糕的设计(只需查看Properties类) - 这就是为什么你可能找不到这样做的库。

没有什么可以阻止您自己扩展java.io.File类,并将所有方法代理到例如Commons VFS API的FileObject

修改:但是,根据该方法,有些事情可能会失败 - 例如,使用带有父File的{​​{1}}构造函数。

编辑2 :好吧,我会从这样的事情开始:

File

至于为什么public class VirtualFile extends java.io.File { public static VirtualFile fromFile(File file) { if (file instanceof VirtualFile) { return (VirtualFile) file; } else { FileSystemManager fsm = new DefaultFileSystemManager(); return fsm.toFileObject(file); } } private final org.apache.commons.vfs.FileObject mProxyFileObject; public VirtualFile(FileObject proxy) { super("/tmp/xxxx"); // That part needs some work to be cross-platform. // However, such a construction will completely // destroy the expectations that other classes // have about what a File is. mProxyFileObject = proxy; } public VirtualFile(VirtualFile parent, String child) { this(parent.mProxyFileObject.resolveFile(child)); } public VirtualFile(File parent, String child) { this(fromFile(parent), child); } @Override public boolean canExecute() { throw new UnsupportedOperationException(); } @Override public boolean canRead() { try { return mProxyFileObject.isReadable(); } catch (FileSystemException fse) { // FileSystemException is not a Runtime Exception :( throw new RuntimeException(fse); } } // Override ALL public methods to throw Exceptions; // implement or mock only the methods that you need. } 构造函数无法使用该设置:该构造函数不期望File(File, String)的实现会破坏类的合同 - 我们在调用File时会这样做。 (我们无法避免破坏类的合同,因为我们想要使用的虚拟文件没有明确的super("/tmp/xxxx")等价物)

所以,你有 - 它需要一些重要的工作,并且很有可能图书馆不会按预期工作。