Java BufferedReader--通过令牌而不是readLine()读取?

Java BufferedReader--通过令牌而不是readLine()读取?,java,bufferedreader,Java,Bufferedreader,有没有办法从BufferedReader读取,直到它到达一个不是换行符或回车符的字符(readLine()就是这样做的) 我不想读一行然后分开。我想忽略新行和返回车厢,只考虑一个特定的令牌(如Tab),具有BuffelDead阅读器性能。 < P>这不是很优雅,但可能起作用。 将openjdk BufferedReader源代码复制到另一个包中(JVM不会让您的类加载器覆盖任何默认Java类)。你可以从这里得到它-- 创建从该BufferedReader副本扩展的子类,创建构造函数并重写read

有没有办法从BufferedReader读取,直到它到达一个不是换行符或回车符的字符(readLine()就是这样做的)


我不想读一行然后分开。我想忽略新行和返回车厢,只考虑一个特定的令牌(如Tab),具有BuffelDead阅读器性能。

< P>这不是很优雅,但可能起作用。

  • 将openjdk BufferedReader源代码复制到另一个包中(JVM不会让您的类加载器覆盖任何默认Java类)。你可以从这里得到它--
  • 创建从该BufferedReader副本扩展的子类,创建构造函数并重写readLine()。复制原始readLine()实现并粘贴为重写的readLine()
  • 将阻止编译的超类(BufferedReeader)中的所有属性和方法从私有更改为受保护
  • 将子类readLine()中所有提到的\n和]r替换为\t(因此将按选项卡拆分)
  • 瞧——)

    这就是它最终的样子

    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);
                }
            }
        }
    
    }
    
    对于这样的输入

        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();
    
    some string some other string
    some third string after a newline   some forth  
    and so on
    
    结果是

    some string
    some other string
    some third string after a newline
    some forth
    
    and so on
    
    然而,这看起来是一个非常麻烦的解决方案,所以我真的希望在这里看到其他聪明的答案

    是的

     BufferedReader br = ...
     StringBuilder sb = new StringBuilder(ESTIMATED_LENGTH);
     int ch;
     while ((ch = br.read()) != -1 && ch != '\t') {
         sb.append(ch);
     } 
    
    在最好的情况下,您将获得几乎与
    BufferedReader.readLine()
    一样好的性能。在最坏的情况下,您会执行一到两个额外的字符副本(我认为)。。。这也不算太糟糕,性能达到1

    要获得与
    BufferedReader
    一样好的性能,需要对代码
    BufferedReader
    本身进行黑客攻击。。。或者重写它

    (扩展
    BufferedReader
    的尝试无效,因为您正在从父类调用
    private
    方法。这是不允许的!如果您要通过更改方法访问来“修复”此问题,那么您也可以只“克隆”
    BufferedReader
    类,并将您的方法添加到其中。当然,您的类不再是
    java.io.BufferedReader
    或其子类。)



    1——通过正当理由,考虑大局。如果您正在从某处读取大量数据,那么性能瓶颈可能是I/O或读取令牌后如何处理它们。如果不是这样,那么您可能应该使用1)java.nio/

    CharBuffer
    ,2)自定义I/O堆栈或3)其他编程语言。

    对于类似的情况,您甚至不应该使用BufferedReader。我会这样使用NIO:

    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();
        }
    }
    
    如果您只想要一个角色,您可以:

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

    要忽略新行并返回,只需将readLine参数设置为: 字符串读取行(true);
    并实现一个条件来检测选项卡。

    实际上,步骤1到4显示我正在使用BufferedReader的副本,并且所有私有属性和方法都已更改为受保护(步骤3)您可以将BufferedReader包装在扫描仪中。我同意这可以解决问题,但对于足够大的文本文件来说可能不是一个好主意(例如,服务器日志)