Можно ли создать диск RAM Java для использования с API java.io. *? - PullRequest
9 голосов
/ 13 декабря 2010

Я использую стороннюю библиотеку, которая в основном создает выходной каталог с различными типами файлов и подкаталогов внутри.Я хотел бы иметь возможность писать модульные тесты, чтобы подтвердить, что вывод правильный.

Я хотел бы иметь возможность использовать библиотеку с диском RAM, чтобы ничто из того, что библиотека делает, не затрагивало фактические дисковые пластины втем не мение.Идея состоит в том, чтобы сделать тесты очень быстрыми для запуска и очистки (сбросить RAM-диск?).

Для меня доступны два наиболее важных варианта: Commons VFS и JSR 203.Первый бесполезен для меня, потому что я хочу, чтобы все работало прозрачно с использованием API java.io. *, а не классов Commons VFS.Позднее это не сработает, потому что я должен обойтись с JDK 6 (он должен быть частью JDK 7), и я не знаю, будет ли он работать без проблем с java.io. * в любом случае (я бы не сталпоспорим на это).

Также есть другие решения, но я не могу использовать их по той же причине, по которой я не могу использовать Commons VFS.О мошенничестве не может быть и речи из-за сложности рассматриваемой библиотеки.

На моей машине с Linux я могу легко создать ОЗУ и использовать API java.io. * так же, как и с файламина диске.Дело в том, что я хочу, чтобы он был кроссплатформенным, а точнее, чтобы настройка диска была частью процедуры тестирования, а не чем-то внешним.

Итак, есть ли способ зарегистрировать диск RAM вJava, которая будет использоваться со стандартным java.io. * API?

Ответы [ 3 ]

6 голосов
/ 13 декабря 2010

Итак, есть ли способ зарегистрировать RAM-диск на Java, который можно было бы использовать со стандартным java.io. * API?

Не с Java 6 или более ранней JVM,Java 6 и более ранние версии не предоставляют SPI для регистрации файловых систем или типов файловых систем.Итак, для реализации FS ОЗУ, которую приложение будет использовать как обычную FS, потребуется изменение поведения ряда java.io.* классов.

Я думаю, что лучшее, что вы могли бы сделать, это использоватьRAM FS, реализованная операционной системой хоста.Вы должны иметь доступ к нему из Java, как если бы это была обычная файловая система.Однако ввод / вывод повлечет за собой системные вызовы, поэтому он не будет таким быстрым, как если бы файловая система RAM была сохранена в управляемой памяти JVM.

4 голосов
/ 13 декабря 2010

Теоретически Стивен прав. Но я могу предложить вам хитрость. Вы можете реализовать свои собственные FileInputStream и FileOutputStream и поместить их в путь загрузки. Ваша реализация, например, реализует open (), read () и readBytes () (которые являются родным методом в обычном FileInputStream.)

Это чисто Java-решение для вашей проблемы. Его недостатком является то, что вы должны запускать свои тесты в отдельном экземпляре JVM.

1 голос
/ 13 декабря 2010

Основная проблема, которую вы хотите преодолеть, заключается в том, что оригинальные java.io API вообще не являются гибкими (все они относятся к конкретным классам). Единственный способ, которым вы можете добавить различные функции, например java.io.File, - это расширение базового класса.

Расширение классов после их разработки может быть плохим проектом (просто посмотрите на класс Properties) - вот почему вы, вероятно, не найдете библиотеку, которая делает это.

Ничто не мешает вам самостоятельно расширять класс java.io.File и передавать все методы, например, для FileObject API Commons VFS.

Редактировать : Однако есть вещи, которые, вероятно, потерпят неудачу при таком подходе - например, использование конструкторов 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 эквивалента)

Итак, вот вам - это потребует нетривиальной части работы, и есть большая вероятность того, что библиотека все равно не будет работать так, как ожидалось.

...