BlogtimeException

By Behrang Saeedzadeh (the 5th incarnation)

Reading a File in Java -- Beautifully

,

Till today, I used to read an entire text file like this:

String newLine = System.getProperty("line.separator");

StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
   sb.append(line).append(newLine);
}
return sb.toString();

That's not beautiful. But today I came up with this alternative:

String newLine = System.getProperty("line.separator");

StringBuilder sb = new StringBuilder();
for (String line = br.readLine(); line != null; line = br.readLine()) {
   sb.append(line).append(newLine);
}
return sb.toString();

And I like its beauty. What do you think? Isn't this more beautiful? sherlock It would be more convenient if BufferedReader had a readFile() method though. Also it makes sense to make BufferedReader iterable so we could have:

for (String line : buffReader) {
   // do something with line
}

EJB-to-Client NotificationJava and Mac OSX: The right time, the right choice

Comments

Unregistered user Thursday, October 25, 2007 12:10:37 PM

Stephan Schmidt writes: When you do that often, why not write your own FileReader returning a Iterator<Sting> object. Shouln't be more than 10 lines of code. Peace -stephan -- Stephan Schmidt :: stephan@reposita.org Reposita Open Source - Monitor your software development http://www.reposita.org Blog at http://stephan.reposita.org - No signal. No noise.

Unregistered user Thursday, October 25, 2007 2:31:33 PM

Anonymous writes: Try this: Scanner scanner = new Scanner(file); scanner.useDelimiter("\\A"); String content = scanner.next(); scanner.close(); return content;

Unregistered user Thursday, October 25, 2007 3:04:00 PM

Stephan writes: @Anon: Excellent suggestion. Didn't know about that class in the 1.5 JDK. Thanks -stephan

Behrang Saeedzadehbehrangsa Thursday, October 25, 2007 5:23:52 PM

@Stephan,

That makes sense, but every now and then that I have to experiment with something or write a tiny small project (say, less than 1000 lines), if I need to read form a file, I usually do that manually. It is not that cumbersome after all. I don't know why I hesitate to create my common utilities JAR file. Oh, btw, Commons IO has this neat readFileToString() method but again, I refuse to use extra libs for my small projects. Maybe I prefer this approach, because in general, I like to have a minimal dependency on external JAR files. Maybe I have to rethink about this attitude of mine thought.

One cool thing to do is to write a code snippet template in IDEA or Eclipse , say named rdfl (for readfile), and then by expanding it, it would insert the above chunk of code (something a little bit more complex) at caret position.

@Anonymous,

That was even more beautiful, but I assume more resource hungry, which is of course not important at all for a small experimental project.

Unregistered user Thursday, October 25, 2007 8:23:48 PM

Joe Attardi writes: How is this "beautiful"? It's the intended use of a for loop.

Behrang Saeedzadehbehrangsa Thursday, October 25, 2007 9:48:43 PM

@Joe,

Almost everywhere, I have seen people using the while-loop approach for reading files. This leaves a line variable in a broader scope than it is necessary to be. Of course, this peice of code is usually wrapped inside a method. But again, IMO, the for loop is more beautiful than the while loop. Trivial but worthy nonetheless.

Unregistered user Saturday, October 27, 2007 9:39:50 PM

Peter Lawrey writes: This is a bit longer than 10 lines but the end result is elegant, I might use this in future. public class LineReader { public static Iterable<String> readText(final String filename) { return new Iterable<String>() { public Iterator<String> iterator() { final BufferedReader br; try { br = new BufferedReader(new FileReader(filename)); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } return new Iterator<String>() { String line = null; public boolean hasNext() { try { line = br.readLine(); } catch (IOException e) { line = null; close(); throw new IllegalStateException(e); } if (line == null) close(); return line != null; } public String next() { if (line == null) throw new NoSuchElementException(); return line; } public void remove() { throw new UnsupportedOperationException(); } protected void finalize() throws Throwable { super.finalize(); close(); } private void close() { try { br.close(); } catch (IOException ignored) { // ignored or logged on debug. } } }; } }; } public static void main(String ... args) { for(String line: readText(args[0])) { System.out.println(line); } } }

Unregistered user Saturday, October 27, 2007 9:40:51 PM

Peter Lawrey writes: The formattings not the best. :) <pre> public class LineReader { public static Iterable<String> readText(final String filename) { return new Iterable<String>() { public Iterator<String> iterator() { final BufferedReader br; try { br = new BufferedReader(new FileReader(filename)); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } return new Iterator<String>() { String line = null; public boolean hasNext() { try { line = br.readLine(); } catch (IOException e) { line = null; close(); throw new IllegalStateException(e); } if (line == null) close(); return line != null; } public String next() { if (line == null) throw new NoSuchElementException(); return line; } public void remove() { throw new UnsupportedOperationException(); } protected void finalize() throws Throwable { super.finalize(); close(); } private void close() { try { br.close(); } catch (IOException ignored) { // ignored or logged on debug. } } }; } }; } public static void main(String ... args) { for(String line: readText(args[0])) { System.out.println(line); } } } </pre>

Behrang Saeedzadehbehrangsa Saturday, October 27, 2007 10:57:48 PM

@Peter

Looks like Opera is facing some issues regarding the formatting of comments for the time being: http://my.opera.com/community/forums/topic.dml?id=210362 but your LineReader was interesting.

Unregistered user Saturday, December 1, 2007 6:30:00 PM

Anonymous writes: Hello! I have a problem. I have to write a method in order to return a the next line from a file. When I call de method always returns the first line.What can I do? public String nextEntry()throws IOException { BufferedReader br= new BufferedReader(new FileReader("file.txt")); return br.readLine(); }

Unregistered user Friday, January 4, 2008 12:42:51 AM

Anonymous writes: Anonymous, you're reinitialising your BufferedReader everytime nextEntry() is called, you need to declare it outside of the method. That way its state will persist.

Unregistered user Monday, January 28, 2008 5:25:51 AM

Anonymous writes: you guys are total fags

Unregistered user Tuesday, February 19, 2008 10:32:23 PM

Anonymous writes: if you like the simplicity of the for-loop, then why do you have the call to readLine() twice. You should do: for( String line; (line = reader.readLine()) != null; ) { }

Unregistered user Monday, July 27, 2009 4:53:57 PM

OneLiner writes: for (String line; (line = br.readLine()) != null; sb.append(line).append(newLine));

Unregistered user Monday, May 10, 2010 3:04:20 PM

drozzy writes: I am tackling the same problem, and I've posted a question on stackoverflow about it. I also proposed a simple solution (which is a bit hacky). I would appreciate if java-gurus could weight-in. See: http://stackoverflow.com/questions/2802711/python-like-java-io-library

Write a comment

New comments have been disabled for this post.