1

I have a jar file which contains a bunch of files in /dict/ folder. So I added it as a maven dependency. Then in order to create RandomAccessFile for a file, I read it as a resource, put into File, and then give it to the RandomAccessFile constructor. Here is how things are done:

URL resourceURL = getClass().getResource("/dict/index.verb" );
System.out.println("----> file " + resourceURL.getFile());
File f = new File(resourceURL.getFile());
System.out.println("Can read = " + f.canRead());
try {
    RandomAccessFile _file = new RandomAccessFile(f, "r");
    System.out.println(_file.length());
} catch (java.io.IOException e) {
    e.printStackTrace();
}

Here is the output:

----> modified file file:/Users/i-danielk/.m2/repository/edu/illinois/cs/cogcomp/wordnet/1.0/wordnet-1.0.jar!/dict/index.verb
Can read = false
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at junit.framework.TestCase.runTest(TestCase.java:168)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:243)
    at junit.framework.TestSuite.run(TestSuite.java:238)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
java.io.FileNotFoundException: file:/Users/i-danielk/.m2/repository/edu/illinois/cs/cogcomp/wordnet/1.0/wordnet-1.0.jar!/dict/index.verb (No such file or directory)
    at java.io.RandomAccessFile.open0(Native Method)

An issue I noticed is that, using File(...) is not a good idea for reading resources.

But now I am not sure what is the best we to read the do the whole procedure without having File as an intermediate step.

Community
  • 1
  • 1
Daniel
  • 5,839
  • 9
  • 46
  • 85
  • Resources are not files, they are not held in file systems, and you cannot perform random access on them. You can get them as URLs or streams, period. – user207421 Nov 16 '15 at 02:58

1 Answers1

2

URL#getFile isn't doing what you think it is and you should read the JavaDocs to find out what it does do.

Instead, you should use something like URL#openStream and write the contents out to a physical File yourself.

As a rough example...

URL resourceURL = getClass().getResource("/dict/index.verb");
File output = new File("some file somewhere");
try (InputStream is = resourceURL.openStream(); OutputStream os = new FileOutputStream(output)) {
    byte[] buffer = new byte[2048];
    int bytesRead = -1;
    while ((bytesRead = is.read(buffer)) != -1) {
        os.write(buffer, 0, bytesRead);
    }
} catch (IOException exp) {
    exp.printStackTrace();
}

You might find File.createTempFile of some use

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • So I should read the resource, write it, and then read it into `RandomAccessFile`? Isn't it inefficient? – Daniel Nov 16 '15 at 03:01
  • Your resource is a series of compressed bytes in side a Jar (zip) file (with a bunch of other compressed bytes). You can read it like you would a normal file, because it's not. Instead, you need to extract the contents to a file system file and then read it. Also remember, you won't be able to write to this resource (you should accept that for now because it's a complete pain to update a running Jar file which fails more often then it succeeds) – MadProgrammer Nov 16 '15 at 03:07