Leonardo Kenji Shikida
Leonardo Kenji Shikida

Reputation: 751

BufferedReader -- read by token instead of readLine()?

Is there any way to read from a BufferedReader until it reaches a char that is not newline or return carriage (which is what readLine() does)?

I don't want to read a line and then split. I want to ignore newlines and return carriages and consider only a specific token (such as tab) with BufferedReader performance.

Upvotes: 1

Views: 2551

Answers (4)

user3771889
user3771889

Reputation: 9

To ignore the new line and return just set your readLine argument to: String readLine(true); And implement a conditional to detect tabs.

Upvotes: 0

JD9999
JD9999

Reputation: 426

For something like this, you shouldn't even use BufferedReader. I would use NIO like so:

public String[] splitContentsBy(String split, File file){
    try{
        byte[] bytes = Files.readAllBytes(file);
        String contents = new String(bytes);
        String[] array = contents.spilt(split);
    }catch(IOException e){
        e.printStackTrace();
    }
}

If you only want a character, you can have:

char c = '?'; //A question mark, as an example.
String[] parts = splitContentsBy(String.valueOf(c), new File("file.txt");

Upvotes: 2

Stephen C
Stephen C

Reputation: 718836

Yea sure.

 BufferedReader br = ...
 StringBuilder sb = new StringBuilder(ESTIMATED_LENGTH);
 int ch;
 while ((ch = br.read()) != -1 && ch != '\t') {
     sb.append(ch);
 } 

In the best case, you are going to get performance that is as almost as good as BufferedReader.readLine(). In the worst case, you perform one to two extra copies of the characters (I think) ... which isn't too bad a performance hit1.

Getting performance that is as good as BufferedReader is going to require hacking the code BufferedReader itself ... or rewriting it.

(Your attempt at extending BufferedReader does not work because you are calling private methods from the parent class. That is not allowed! If you are going to "fix" that by changing the method access, then you may as well just "clone" the BufferedReader class and add your methods to it. Of course, your class is no longer a java.io.BufferedReader or a subclass of it.)


1 - By way of justification, consider the big picture. If you are reading large amounts of data from somewhere, the performance bottleneck is likely to be either I/O or what you do with the tokens after reading them. If that's not the case, then you should probably be using 1) java.nio / CharBuffer, 2) a custom I/O stack or 3) another programming language.

Upvotes: 1

Leonardo Kenji Shikida
Leonardo Kenji Shikida

Reputation: 751

this is not very elegant, but may work.

  1. copy openjdk BufferedReader source into another package (JVM won't let your classloader override any default Java class). You can get it from here -- http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/io/BufferedReader.java/?v=source
  2. create a subclass that extends from this BufferedReader copy, create the constructors and override readLine(). Copy the original readLine() implementation and paste as the overriden readLine()
  3. change all attributes and methods from the superclass (BufferedReeader) that are blocking the compilation from private to protected
  4. replace all mentions to \n and ]r in the subclass readLine() to \t instead (so you're gonna split by tab)

voilà :-)

this is how it will look like in the end

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

public class MyBufferedReader extends BufferedReader {

    /**
     * 
     * @param in
     */
    public MyBufferedReader(Reader in) {
        super(in);

    }

    @Override
    String readLine(boolean ignoreLF) throws IOException {
        StringBuffer s = null;
        int startChar;

        synchronized (lock) {
            ensureOpen();
            boolean omitLF = ignoreLF || skipLF;

        bufferLoop:
            for (;;) {

                if (nextChar >= nChars)
                    fill();
                if (nextChar >= nChars) { /* EOF */
                    if (s != null && s.length() > 0)
                        return s.toString();
                    else
                        return null;
                }
                boolean eol = false;
                char c = 0;
                int i;

                /* Skip a leftover '\n', if necessary */
                if (omitLF && (cb[nextChar] == '\t'))
                    nextChar++;
                skipLF = false;
                omitLF = false;

            charLoop:
                for (i = nextChar; i < nChars; i++) {
                    c = cb[i];
                    if (c == '\t') {
                        eol = true;
                        break charLoop;
                    }
                }

                startChar = nextChar;
                nextChar = i;

                if (eol) {
                    String str;
                    if (s == null) {
                        str = new String(cb, startChar, i - startChar);
                    } else {
                        s.append(cb, startChar, i - startChar);
                        str = s.toString();
                    }
                    nextChar++;
                    if (c == '\t') {
                        skipLF = true;
                    }
                    return str;
                }

                if (s == null)
                    s = new StringBuffer(defaultExpectedLineLength);
                s.append(cb, startChar, i - startChar);
            }
        }
    }

}

you can use it like this

    MyBufferedReader my = new MyBufferedReader(new InputStreamReader(Main.class.getResourceAsStream("fileWithTabs.txt")));
    String line = null;
    while((line = my.readLine())!=null) {
        System.out.println(line);
    }
    my.close();

for an input like this

some string some other string
some third string after a newline   some forth  
and so on

result is

some string
some other string
some third string after a newline
some forth

and so on

however, looks like a very very cumbersome solution, so I really would like to see other clever answers here

Upvotes: 0

Related Questions