Home > development, java, opensource > A BufferedReader which returns line terminators

A BufferedReader which returns line terminators

I am working on a parser which must take into account line numbers, and make correlations between them and document’s offsets. For instance, I need to know at which line is the character #145 of a given text file. The problem is that different OSs use different line terminators: \n on Linux, \r\n on Windows, \r on Mac.

I could not modify the original document in any way, so I needed a trustable way to work on them in a platform-independent way. One simple way to count lines in a text file would be using Java’s BufferedReader. Unfortunately this class provides no way of knowing which line terminators are used for every line of text, what prevents using the lenght of the read buffer to determinate the current offset while reading.
That’s why I wrote this simple class.It provides two methods: readLine(), working as the usual BufferedReader’s one, but returning also line terminators (at the end of the line), and a readChars(), useful for knowing the current offset while reading the stream.

I wrote some tests also to test if it works in any case, and so far I didn’t know of unsolved problems. Feel free to use it if you want, and let me know if you find any bug.

import java.io.IOException;
import java.io.Reader;

public class MyBufferedReader {
 private Reader delegate;
 private StringBuilder readBuffer;
 private int nextCh = SOL;
 private int readChars;

 private static final int SOL = -10;   // Start Of Line

 public TplBufferedReader(Reader delegate) {
 this.delegate = delegate;
 readBuffer = new StringBuilder();
 }

 /**
 * Reads all chars of a line, returning also line terminators
 *
 * @return  The line text
 */
 public String readLine() throws IOException {
 String res = null;
 readBuffer.setLength(0);
 int ch = (char) -10;

 if (nextCh == -1) {
 res = null;
 } else {

 boolean newLine = false;
 boolean eof = false;
 while (!newLine && !eof) {
 if (nextCh != SOL){
 readBuffer.append((char)nextCh);
 }
 nextCh = SOL;
 ch = delegate.read();
 switch (ch) {
 case '\r':
 // check for double newline char
 nextCh = delegate.read();
 if (nextCh == '\n') {
 // double line found
 readBuffer.append("\r\n");
 newLine = true;
 nextCh = SOL;
 } else {
 readBuffer.append("\r");
 newLine = true;
 }
 break;
 case '\n':
 readBuffer.append("\n");
 newLine = true;
 break;
 case -1:
 eof = true;
 nextCh = -1;
 break;
 default:
 if (ch != -1) readBuffer.append((char)ch);           
 }       
 }
 res = readBuffer.toString();
 readChars += res.length();
 }
 return res;
 }

 public void close() throws IOException{
 delegate.close();
 }

 public int readChars() {
 return readChars;
 }
}
Advertisement
Categories: development, java, opensource
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.