creating a virtual file system with JIMFS

10k Views Asked by At

I'd like to use Google's JIMFS for creating a virtual file system for testing purposes. I have trouble getting started, though.

I looked at this tutorial: http://www.hascode.com/2015/03/creating-in-memory-file-systems-with-googles-jimfs/

However, when I create the file system, it actually gets created in the existing file system, i. e. I cannot do:

Files.createDirectory("/virtualfolder");

because I am denied access.

Am I missing something?

Currently, my code looks something like this:

Test Class:

FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path vTargetFolder = fs.getPath("/Store/homes/linux/abc/virtual");

TestedClass test = new TestedClass(vTargetFolder.toAbsolutePath().toString());

Java class somewhere:

targetPath = Paths.get(targetName);
Files.createDirectory(targetPath);

// etc., creating files and writing them to the target directory

However, I created a separate class just to test JIMFS and here the creation of the directory doesnt fail, but I cannot create a new file like this:

FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path data = fs.getPath("/virtual");
Path dir = Files.createDirectory(data);
        
Path file = Files.createFile(Paths.get(dir + "/abc.txt")); // throws NoSuchFileException

What am I doing wrong?

4

There are 4 best solutions below

0
On BEST ANSWER

The problem is a mix of Default FileSystem and new FileSystem.

Problem 1:

Files.createDirectory("/virtualfolder"); 

This will actually not compile so I suspect you meant:

Files.createDirectory( Paths.get("/virtualfolder"));

This attempts to create a directory in your root directory of the default filesystem. You need privileges to do that and probably should not do it as a test. I suspect you tried to work around this problem by using strings and run into

Problem 2:

Lets look at your code with comments

FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
// now get path in the new FileSystem
Path data = fs.getPath("/virtual");    
// create a directory in the new FileSystem
Path dir = Files.createDirectory(data);
// create a file in the default FileSystem 
// with a parent that was never created there
Path file = Files.createFile(Paths.get(dir + "/abc.txt")); // throws NoSuchFileException

Lets look at the last line:

dir + "/abc.txt"            >> is the string "/virtual/abc.txt"
Paths.get(dir + "/abc.txt") >> is this as path in the default filesystem

Remember the virtual filesystem lives parallel to the default filesystem. Paths have a filesystem and can not be used in an other filesystem. They are not just names.

Notes:

  • Working with virtual filesystems avoid the Paths class. This class will always work in the default filesystem. Files is ok because you have create a path in the correct filesystem first.

  • if your original plan was to work with a virtual filesystem mounted to the default filesystem you need bit more. I have a project where I create a Webdav server based on a virtual filesystem and then use OS build in methods to mount that as a volume.

2
On

In your shell try ls / the output should contain the "/virtual" directory.

If this is not the case which I suspect it is then:

The program is masking a:

java.nio.file.AccessDeniedException: /virtual/abc.txt

In reality the code should be failing at Path dir = Files.createDirectory(data);

But for some reason this exception is silent and the program continues without creating the directory (or thinking it has) and attempts to write to the directory that doesn't exist

Leaving a misleading java.nio.file.NoSuchFileException

3
On

I suggest you use memoryfilesystem instead. It has a much more complete implementation than Jimfs; in particular, it supports POSIX attributes when creating a "Linux" filesystem etc.

Using it, your code will actually work:

try (
    final FileSystem fs = MemoryFileSystemBuilder.newLinux()
        .build("testfs");
) {
    // create a directory, a file within this directory etc
}
0
On

Seems like instead of

Path file = Files.createFile(Paths.get(dir + "/abc.txt"));

You should be doing

Path file = Files.createFile(dir.resolve("/abc.txt"))

This way, the context of dir (it's filesystem) is not lost.