• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Jeanne Boyarsky
  • Liutauras Vilda
Sheriffs:
  • Rob Spoor
  • Bear Bibeault
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:
  • Frits Walraven
  • Himai Minh

Reading Text File

 
Greenhorn
Posts: 27
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I found this code on stackover flow and i hope to use it for a simple homework assignment but im a little confused on what the index != -1 means and why it works



From what i understand is that when java searches for a string in a file and it does not exist, (or perhaps in an array even) the index is considered -1, so as long as it is not -1 it would mean it exists. Not sure if im looking at this correctly or not.
 
Saloon Keeper
Posts: 8220
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You mostly have it right. Because you are reading the file one line at a time the 'if' only tells you if the current line contains "word". This snippet will print "EXISTS" zero or more times depending on how many lines contain "word".
 
Marshal
Posts: 72913
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That code is incomplete and potentially error prone.
  • 1: I would prefer to open the Scanner with a Path argument ...new Scanner(Paths.get("myFile")); See the Java™ Tutorials.
  • 2: You are not closing the Scanner: I think you should always use try with resources to make sure the Scanner is closed correctly.
  • 3: I would prefer to use hasNext() rather than hasNextLine(). That obviates any problems you might have if the file finishes with an empty line. I think the current example won't suffer any problems with empty lines.
  • 4: Use contains() rather than indexOf != -1. More about the String methods here:- 1 2.


  • [Addition] Never close a Scanner reading System.in.
     
    Carey Brown
    Saloon Keeper
    Posts: 8220
    71
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Campbell Ritchie wrote: I would prefer to use hasNext() rather than hasNextLine(). That obviates any problems you might have if the file finishes with an empty line.

    I keep hearing this about using hasNext() instead of hasNextLine() so I had to try it for myself. I purposely made a txt file without a new-line (0d 0a) on the last line. Verified it with a hex dump. And scanned it with both hasNext() and hasNextLine() and both work identically.
     
    Campbell Ritchie
    Marshal
    Posts: 72913
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    In this case you won't notice any difference. If, however, you need to do anything with your lines that requires they be a certain length, then things can go wrong. We had somebody once who split all the lines he read from his file, and of course the last line was 0‑length and could only be split into new String[]{""} and things go wrong as soon as you try for the second element in that array. Unfortunately I couldn't find the thread. It should be easy enough to make a program empty line tolerant, so my empty line sensitive example is rather contrived.

    jshell> class EmptyLineDemo
      ...> {
      ...>     public static void main(String... args)
      ...>     {
      ...>         new EmptyLineDemo(args[0]).readLines();
      ...>     }
      ...>    
      ...>     private final String fileName;
      ...>    
      ...>     EmptyLineDemo(String fileName)
      ...>     {
      ...>         this.fileName = fileName;
      ...>     }
      ...>    
      ...>     void readLines()
      ...>     {
      ...>         int count = 1;
      ...>         try (Scanner scan = new Scanner(Paths.get(fileName)))
      ...>         {
      ...>             while (scan.hasNextLine())
      ...>             {
      ...>                 System.out.printf("line %d has %s-%s%n", count++,
      ...>                 scan.next(), scan.next());
      ...>             }
      ...>         }
      ...>         catch (IOException ex)
      ...>         {
      ...>             ex.printStackTrace();
      ...>         }
      ...>     }
      ...> }
    |  modified class EmptyLineDemo

    jshell> EmptyLineDemo.main("names")
    line 1 has Gurtej-Grewal
    line 2 has Carey-Brown
    line 3 has Campbell-Ritchie
    |  Exception java.util.NoSuchElementException
    |        at Scanner.throwFor (Scanner.java:937)
    |        at Scanner.next (Scanner.java:1478)
    |        at EmptyLineDemo.readLines (#2:23)
    |        at EmptyLineDemo.main (#2:5)
    |        at (#3:1)

    I didn't intentionally write an empty line, but maybe it was added regardless. I can imagine all sorts of ways to make that code empty line resistant, one of which is to change hasNextLine() to hasNext(). This is what the names file looks like:-I didn't see the empty line, but it is obviously there, or hasNextLine() would return false.
     
    Carey Brown
    Saloon Keeper
    Posts: 8220
    71
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I tried to create a file with no N/L on the last line with VIM. No luck. It put one in anyway. Note pad did it correctly. I had to use a hex dump utility to verify.

    I was reading the source code for hasNextLine() and the thing I found interesting was that there was to explicit code for handling end of file. The method instead relies on a regular expression that matches up to '$'. Then I googled all over the internet to try and find out how '$' does or does not match an EOF. My experiment shows that it does but I was hoping to see some documentation.

    As for your example, yes I can see where that would work, but my experiment shows the simple way works as well, so why jump through the hoops when you don't have to.
     
    Campbell Ritchie
    Marshal
    Posts: 72913
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    As I said, mine was an example contrived to be empty line sensitive. Empty line sensitivity is more a case of what you do with it. If you try anything requiring a certain length of line, the empty line will trip you up, often with an exception. A lot of text editors and WPs add that final newline automatically; LibreOffice does the same. It might be a Unix/Linux thing that they like an empty line at the end of a file, as you would have in a C source file or a .jar manifest file.

    . . .  hasNextLine() . . . there was to explicit code for handling end of file. The method instead relies on a regular expression that matches up to '$'. . . .

    Scanner does lots of things with regular expressions behind the scenes; it even says that in its documentation:-

    A simple text scanner which can parse primitive types and strings using regular expressions.

    It took me a long time to realise that the adjectives associate to the left not to the right; it is the text that is described as simple, presumably as opposed to HTML/XML tags. What's EOF in hex? Wikipedia isn't that helpful about that question, but suggests sometimes −1 is used. I presume there isn't an EOF appended to any of the files. Obviously the OS has a mechanism for reporting an end of file situation, even if it doesn't use an EOF character. You can find “$” in the Pattern documentation.
    That starts to explain why Scanner behaves differently from BufferedReader. To a Scanner my names file has four lines, the last being empty/zero‑length. To a buffered reader there are three lines and once those have been read it returns null. It is presumably buffering input from those abominable read() methods (e.g. 12) and is interpreting a −1 returned as an EOF situation. And the final newline doesn't constitute a next line to a buffered reader, but it does to a Scanner.

    [edit] WPs = word processors
     
    Campbell Ritchie
    Marshal
    Posts: 72913
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    There is nothing to stop you combining hasNext() and nextLine():-
     
    Campbell Ritchie
    Marshal
    Posts: 72913
    330
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Congratulations Have a cow for having this thread quoted in the May 2021 JavaRanch Journal.
     
    When it is used for evil, then watch out! When it is used for good, then things are much nicer. Like this tiny ad:
    Thread Boost feature
    https://coderanch.com/t/674455/Thread-Boost-feature
    reply
      Bookmark Topic Watch Topic
    • New Topic