繁体   English   中英

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

[英]Can a java RAM disk be created to be used with the java.io.* API?

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

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

我可以使用的两个最突出的选项是Commons VFSJSR 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

编辑 :但是,有些事情可能会在该方法下失败 - 例如,使用带有父FileFile构造函数。

编辑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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM