I was working on a parser for a programming project a few weeks ago for school in which reading an input file one character at a time proved to be the easiest route to take. While I found a few different resources online that provided some guidance, but I ran into a somewhat unexpected problem that was difficult to debug regarding detecting the end of stream (EOS)/end of file. This solution is not earth shattering (pretty intuitive actually), but I would have liked to have read something similar to this beforehand. It would have saved me a bit of time.
To clarify, my goal was to take in and parse/analyze an input text file one character at a time (file specified via a command line argument). The simplest way I found in Java to read a character at a time was through a FileReader. There may be a faster/more efficient input method, but simplicity worked fine for the particular project. The following is the rough syntax of how to read from a file (saving the current character each time as a char) and loop through until the end of the file.
char currentChar; //This will store the current character
//Create file reader
FileReader inputStream = new FileReader("file path as a string");
while (currentChar != (char)-1) // This is key!
currentChar = (char)inputStream.read(); // Cast to a char
/* Now perform task! */
The issue I ran into had to do with the way the end of stream was recognized. When reading from a FileReader, the character integer value is returned, so a cast has to be done. The issue is that the EOF is signaled by the integer -1 and not an actual character.
At first, I just tried to compare the character to the integer value -1… basically just hoping for the best. I (stupidly) hoped -1 would be considered a character.
while (currentChar != -1)
This led to an infinite loop, as an actual character (recall I casted directly on the read) is never equal to a -1 integer value. Upon tracing in the Eclipse debugger, the cast to -1 returned an unrecognizable character… not -1.
I then edited my code so that I didn’t cast the input right away. This way I could easily check for the -1 int value. Therefore, currentChar was actually an integer value. Anytime I wanted to perform some sort of operation using this read character, I had to cast it. This lead to A LOT of casts (I was reading it in as a character for a reason) and just made for cluttered code.
As you can see above, I finally realized that I could simply cast (-1) to a character and check for equality that way in the while loop condition. This way I could cast immediately to a character when reading in and not worry about it from that point on.
Hope it helps!