0

Simple enough, I'm attempting to read a text file that is compiled in the jar that is being run.
so the file structure would look something like this

test.jar

-main.class

-META.INF

--MAINFEST.MF

-lists

--readfrom.txt

I've looked around a saw someone had a similar issue to me, Reading File In JAR using Relative Path I attempted that but got an error. Here is what I adapted from it

 List<String> testList = new ArrayList<>();
 try {
                InputStream configStream = getClass().getResourceAsStream("lists\\readfrom.txt");
                BufferedReader configReader = new BufferedReader(new InputStreamReader(configStream, "UTF-8"));
                File file = new File(String.valueOf(configReader));
                Scanner scanner = new Scanner(file);
                while (scanner.hasNextLine()) {
                    testList.add(scanner.nextLine());
                }
                scanner.close();
            }

I ran that and got the error

java.io.FileNotFoundException: java.io.BufferedReader@4cf57088 (The system cannot find the file specified)

Is there anything I'm missing or this the wrong approach?

This is what I have so far

List<String> testList = new ArrayList<>();
 try {
                //what ever needs to happen
                File file = new File(filepath);
                Scanner scanner = new Scanner(file);
                while (scanner.hasNextLine()) {
                    testList.add(scanner.nextLine());
                }
                scanner.close();
            }

I just want this to read the file and add each line as a new item to the list.

  • Your reading a relative path, you want to be reading an absolute path if it's from the classpath. So start with / like "/filename.txt" – Christian B Oct 21 '19 at 23:04
  • @ChristianB Makes no difference, since the class is in the root of the jar file (unnamed package). – Andreas Oct 21 '19 at 23:04

1 Answers1

0

String.valueOf(configReader) does not do what you think it does. It just gives you a string representation of the Reader object, for debugging purposes, e.g. java.io.BufferedReader@4cf57088

Since you seem to want to read the content of the file using Scanner, you should look at the list of constructors available for the Scanner class.

When you do, you might find that Scanner(InputStream source, String charsetName) is the best choice for you.

Side note: You should use try-with-resources.

Your code then becomes:

List<String> testList = new ArrayList<>();
try (Scanner scanner = new Scanner(getClass().getResourceAsStream("lists\\readfrom.txt"), "UTF-8")) {
    while (scanner.hasNextLine()) {
        testList.add(scanner.nextLine());
    }
}

However, since you're only doing line-reading, you should use BufferedReader instead of Scanner, because Scanner is very slow.

List<String> testList = new ArrayList<>();
try (InputStream configStream = getClass().getResourceAsStream("lists\\readfrom.txt");
     BufferedReader configReader = new BufferedReader(new InputStreamReader(configStream, "UTF-8"))) {
    for (String line; (line = configReader.readLine()) != null; ) {
        testList.add(line);
    }
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Interesting, I thought BufferedReader was a archaic version of Scanner. Thank you so much –  Oct 21 '19 at 23:09
  • @user3831093 Oh no, far from it. `Scanner` is an *error-prone* class for breaking text into tokens using regex. It is simple to use when you know that input is valid (or don't care), but is cumbersome to get to work right when error handling is needed, and it is overkill if you don't need tokenization. – Andreas Oct 21 '19 at 23:16
  • @user3831093 To "prove" that `BufferedReader` is not considered archaic, especially compared with `Scanner`, remember that regex was added in Java 1.4 *(2002)*, and `Scanner` was added in Java 5 *(2004)*, but when they added [NIO.2](https://docs.oracle.com/javase/tutorial/essential/io/fileio.html) in Java 7 *(2011)*, the `Files` class had a [`newBufferedReader(Path path, Charset cs)`](https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#newBufferedReader(java.nio.file.Path,%20java.nio.charset.Charset)) method, but no helper method for getting a `Scanner` object. – Andreas Oct 21 '19 at 23:21
  • *Personal opinion:* I consider `Scanner` a bastard class of the Java Runtime Library, used mostly by beginners, or for very simple programs, but I have never used it for real "production" code. – Andreas Oct 21 '19 at 23:28