0

I have a log file that I am reading to a string

public static String read (String path) throws IOException {
   StringBuilder sb = new StringBuilder();
   FileInputStream fs = new FileInputStream(path);
   InputStream in = new BufferedInputStream(fs);

   int r;
   while ((r = in.read()) != -1) {
       sb.append((char)r);
   }

   fs.close();
   in.close();

   return sb.toString();
}

Then I have a parser that iterates over the entire string once

void parse () {
   String con = read("log.txt");
   for (int i = 0; i < con.length; i++) {
       /* parsing action */
   }
}

This is hugely a waste of cpu cycles. I loop over all the content in Read. Then I loop over all the content in Parse. I could just place the /* parsing action */ under the while loop in the Read method, which would be find but I don't want to copy the same code all over the place.

How can I parse the file in one iteration over the contents and still have separate methods for parsing and reading?

In C# I understand there is some sort of yield return thing, but I'm locked with Java.

What are my options in Java?

Patrick Lorio
  • 5,520
  • 11
  • 45
  • 74
  • Is there a reason not to do it as soon as you read the line, As I understood the question we could do a pattern match right after read line, or am I missing something? – add-semi-colons Jun 30 '12 at 21:23
  • If this is really how you read a text file, you have more important problems to solve than memory and CPU usage. – JB Nizet Jun 30 '12 at 21:47
  • You're reading bytes instead of characters, every byte is read as an int, and the String representation of this int is appended to a StringBuilder. If your file contains ABC in ASCII, your String will be "656667". And I don't even mention that you don't close your streams, and that you don't respect Java naming conventions. – JB Nizet Jun 30 '12 at 22:02

1 Answers1

2

This is hugely a waste of cpu cycles. I loop over all the content in Read. Then I loop over all the content in Parse. I could just place the /* parsing action */ under the while loop in the Read method, which would be find but I don't want to copy the same code all over the place.

It's worse than just a huge waste of cpu cycles. It's a huge waste of memory to read the entire file into a string, if you're only going to use it once and the use is looking at one character at a time moving forward, as your code indicates. And if your file is large, you'll exhaust memory.

You should parse as you read, and never have the entire file loaded into memory at once.

If the parsing action needs to be called from more than one place, make it a function and call it rather than copying the same code all over the place. Copying a single-line function call is fine.

Don Roby
  • 40,677
  • 6
  • 91
  • 113
  • I'll probably end up doing that, but is there anything in Java like yield return or should I just forget about that? – Patrick Lorio Jun 30 '12 at 21:32
  • This [related question](http://stackoverflow.com/questions/1980953/is-there-a-java-equivalent-to-cs-yield-keyword) might be useful. – Don Roby Jun 30 '12 at 21:39