[英]Can a java RAM disk be created to be used with the java.io.* API?
我正在使用第三方库,它基本上创建了一个输出目录,其中包含不同类型的文件和子目录。 我希望能够编写单元测试来确认输出是否正确。
我希望能够将lib与RAM磁盘一起使用,这样磁带库就不会以任何方式触及实际的磁盘板。 我们的想法是让测试运行和清理非常快(丢弃RAM磁盘?)。
我可以使用的两个最突出的选项是Commons VFS和JSR 203 。 前者对我没用,因为我希望使用java.io. * API而不是Commons VFS类透明地工作。 后者没有削减它因为我必须使用JDK 6(它应该是JDK 7的一部分)而且我不知道它是否能与java.io. *无缝地工作(我不会打赌吧。
还有其他解决方案,但我不能使用它们的原因与我不能使用Commons VFS相同。 由于所涉及的库的复杂性,模拟是不可能的。
在我的linux机器上,我可以轻松地创建一个RAM驱动器并使用java.io. * API,就像我对磁盘上的文件一样。 问题是,我希望它是跨平台的,更具体地说,是让磁盘设置成为测试程序的一部分,而不是外部的东西。
那么,有没有办法在Java中注册一个可以与标准java.io. * API一起使用的RAM驱动器?
那么,有没有办法在Java中注册一个可以与标准java.io. * API一起使用的RAM驱动器?
不适用于Java 6或更早版本的JVM。 Java 6及更早版本不提供用于注册文件系统或文件系统类型的任何SPI。 因此,要实现应用程序将像普通FS一样使用的RAM FS,需要修改许多java.io.*
类的行为。
我认为你能做的最好的事情就是使用主机操作系统实现的RAM FS。 您应该能够从Java访问它,就像它是一个普通的文件系统一样。 然而,I / O 将需要一个系统调用,这样如果RAM文件系统是在JVM持有管理的内存也不会那么快。
理论上斯蒂芬是对的。 但我可以建议你一招。 您可以实现自己的FileInputStream和FileOutputStream并将它们放入bootclasspath。 例如,您的实现将实现open(),read()和readBytes()(这是常规FileInputStream中的本机方法。)
这是针对您的问题的纯java解决方案。 它的缺点是你必须在单独的JVM实例中运行测试。
您要克服的基本问题是原始的java.io
API根本不灵活(它们都是指具体的类)。 您可以将不同功能放入的唯一方法,例如java.io.File
,是通过扩展基类。
在设计类之后扩展类可能是糟糕的设计(只需查看Properties
类) - 这就是为什么你可能找不到那样做的库。
没有什么可以阻止您自己扩展java.io.File
类,并将所有方法代理到例如Commons VFS API的FileObject
。
编辑 :但是,有些事情可能会在该方法下失败 - 例如,使用带有父File
的File
构造函数。
编辑2 :嗯,我会从这样的事情开始:
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")
时会这样做。 (而且我们无法避免违反类的合同,因为我们想要使用的虚拟文件没有普通的File
等价物)
所以,你有 - 它需要一些重要的工作,并且很有可能图书馆无论如何都无法按预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.