2016-05-29 5 views
0

バッファリングされたリーダーから、改行またはリターンキャリッジ(これはreadLine()の機能)でない文字に到達するまで読み込む方法はありますか?BufferedReader - readLine()の代わりにトークンで読み取りますか?

私は行を読んで分割したくないです。改行やキャリッジを無視し、BufferedReaderのパフォーマンスを持つ特定のトークン(タブなど)のみを考慮したいと思います。

+1

バッファドリーダーをスキャナでラップすることができます。 – matt

答えて

0

これはあまり優雅ではありませんが、うまくいく可能性があります。

  1. copy openjdk BufferedReaderのソースを別のパッケージにコピーします(JVMは、クラスローダーがデフォルトのJavaクラスを上書きすることはできません)。ここから取得することができます。http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/io/BufferedReader.java/?v=source
  2. このBufferedReaderのコピーから継承するサブクラスを作成し、コンストラクタを作成してreadLine()をオーバーライドします。
  3. コンパイルをブロックしているスーパークラス(BufferedReeader)のすべての属性とメソッドをプライベートからプロテクトに変更する
  4. すべての表現を\ nと] rに置き換えますサブクラスのreadLine()で、これはそれが最終的には同じよう

    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); 
          } 
         } 
        } 
    
    } 
    
    0をどのように見えるかです:-)ほら

(あなたがタブによってつもり分割している)の代わりに

をトンを\します

この

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

結果のように入力するために、この

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 

で非常に非常に厄介な解決策のように見えるので、私は本当にだろう他の巧妙な答えを見たいのですが

1

確かにそうです。最良の場合には

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

、あなたは同じくらい良いBufferedReader.readLine()としてあるパフォーマンスを得ようとしています。最悪の場合、1〜2文字の余分なコピーを実行します(私はそう思います...)。パフォーマンスはそれほど悪くはありません。

BufferedReaderと同じ良好なパフォーマンスを得るには、BufferedReaderコードをハッキングするか、書き直す必要があります。

(親クラスからprivateメソッドを呼び出しているため、BufferedReaderを拡張しようとしても動作しません)これは許可されていません!メソッドのアクセスを変更することでそれを修正する場合は、 「クローン」BufferedReaderクラスと、それにあなたのメソッドを追加もちろん、あなたのクラスはもはやjava.io.BufferedReaderであるか、そのサブクラス)


1 - 。。正当な理由として、大きな絵を考えます。大量のデータをどこかから読んでいる場合、パフォーマンスのボトルネックはI/Oまたは読んだ後にトークンを使って何をするかのいずれかになりがちです。そうでない場合は、1)java.nio/CharBuffer、2)カスタムI/Oスタック、または3)別のプログラミング言語を使用しているはずです。

+0

実際には、ステップ1から4まではBufferedReaderのコピーを使用していて、すべてのプライベート属性とメソッドがprotected(ステップ3)に変更されていることを示しています – Leo

1

このような場合は、BufferedReaderを使用しないでください。あなただけのキャラクターをしたい場合は、あなたが持つことができる

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(); 
    } 
} 

:私はそうのようにNIOを使用することになり

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

これは問題を解決しますが、十分な大きさのテキストファイル(例えばサーバーログなど) – Leo

0

新しい行を無視して、戻るにはちょうどにあなたのreadLine引数を設定します。 文字列のreadLine(真実); タブを検出する条件を実装します。

関連する問題