21

メソッドに渡されるタブ区切り文字列 (テーブルを表す) があります。コマンドラインに出力すると、行のある表のように表示されます。

https://i.stack.imgur.com/2fAyq.gif

コマンド ウィンドウは正しくバッファリングされます。私の考えでは、各行の前後に必ず改行文字があります。

私の問題は、着信文字列をテーブルの行を表す個々の文字列に分割したいということです。これまでのところ、私は持っています:

private static final String newLine = System.getProperty("line.separator").toString();
private static final String tab = "\t";
private static String[] rows;
...

rows = tabDelimitedTable.split(newLine);    //problem is here
    
System.out.println();
System.out.println("################### start debug ####################");

System.out.println((tabDelimitedTable.contains(newLine)) ? "True" : "False");
    
System.out.println("#################### end debug###################");
System.out.println();

出力:

################### start debug ####################
False
#################### end debug###################

明らかに、OS に新しい行を開始するように指示する文字列が含まれています。それでも、明らかに改行文字は含まれていません。

Windows XP SP3 で最新の JDK を実行します。

何か案は?

4

7 に答える 7

30

問題

任意の入力テキスト ファイルが「正しい」プラットフォーム固有の改行セパレータを使用していると想定してはなりません。これが問題の原因のようです。正規表現とはほとんど関係ありません。

たとえば、Windows プラットフォームでSystem.getProperty("line.separator")"\r\n"(CR+LF) です。ただし、このプラットフォームで Java コードを実行する場合、行区切り文字が単純な"\n"(LF) の入力ファイルを処理しなければならない場合があります。おそらく、このファイルはもともと Unix プラットフォームで作成されたものであり、バイナリ (テキストではなく) モードで Windows に転送されたものです。現在のプラットフォームの改行区切り記号を使用しない入力としてテキスト ファイルを解析する必要がある、このような状況に遭遇する可能性がある多くのシナリオが考えられます。

(偶然にも、Windows テキスト ファイルがバイナリ モードで Unix に転送されると、多くのエディタが表示^Mされ、何が起こっているのか理解していない人々を混乱させました)。

テキスト ファイルを出力として生成する場合は、おそらくプラットフォーム固有の改行区切りを優先する必要があります、テキスト ファイルを入力として使用する場合、プラットフォーム固有の改行区切りが正しく使用されていると仮定するのはおそらく安全ではありません。


ソリューション

この問題を解決する 1 つの方法は、eg を使用することjava.util.Scannerです。次の行 (存在する場合) を返すことがnextLine()できるメソッドがあり、プラットフォームの改行区切り文字と入力テキスト ファイルの間の不一致を正しく処理します。

2 を組み合わせることもできScannerます。1 つはファイルを 1 行ずつスキャンし、もう 1 つは各行のトークンをスキャンします。各行を に分割する簡単な使用例を次に示しList<String>ます。したがって、ファイル全体がList<List<String>>.

これはおそらく、ファイル全体を 1 つの巨大なファイルに読み込んでから行に分割する (それStringを部分に分割する) よりも優れた方法です。splitsplit

    String text
        = "row1\tblah\tblah\tblah\n"
        + "row2\t1\t2\t3\t4\r\n"
        + "row3\tA\tB\tC\r"
        + "row4";

    System.out.println(text);
    //  row1    blah    blah    blah
    //  row2    1   2   3   4
    //  row3    A   B   C
    //  row4

    List<List<String>> input = new ArrayList<List<String>>();

    Scanner sc = new Scanner(text);
    while (sc.hasNextLine()) {
        Scanner lineSc = new Scanner(sc.nextLine()).useDelimiter("\t");
        List<String> line = new ArrayList<String>();
        while (lineSc.hasNext()) {
            line.add(lineSc.next());
        }
        input.add(line);
    }
    System.out.println(input);
    // [[row1, blah, blah, blah], [row2, 1, 2, 3, 4], [row3, A, B, C], [row4]]

こちらもご覧ください

  • 有効な Java 2nd Edition、項目 25: 配列よりもリストを優先する

関連する質問

于 2010-08-19T08:15:17.853 に答える
29

試す

rows = tabDelimitedTable.split("[" + newLine + "]");

これにより、正規表現の問題が解決するはずです。

また、それほど重要ではありませんが、リターンタイプの

System.getProperty("line.separator")

文字列であるため、toString()を呼び出す必要はありません。

于 2010-08-18T22:06:28.650 に答える
2

BufferedReader.readLine()このすべての複雑さの代わりに試してください。考えられるすべての改行記号を認識します。

于 2010-08-19T09:08:56.847 に答える
2

Windows では、line.separator は CR/LF の組み合わせです (参照はこちら)。

JavaString.split()メソッドは正規表現を取ります。ですから、ここには混乱があると思います。

于 2010-08-18T21:55:48.397 に答える
1

これを試して:

rows = tabDelimitedTable.split("[\\r\\n]+");

これは、入力に含まれる行区切り文字に関係なく機能し、空白行を無視します。

于 2010-08-18T22:21:12.020 に答える
1

あなたの問題は、String.split()その引数を正規表現として扱い、正規表現は改行を特別に扱うことだと思います。渡す正規表現オブジェクトを明示的に作成し(それには別のオーバーロードがあります) 、 の flags パラメータをsplit()渡すことで改行を許可するようにその正規表現を構成する必要がある場合があります。 ドキュメントMULTILINEPattern.compile()

于 2010-08-18T21:52:19.743 に答える
1

split() が引数として正規表現を取るという他のレスポンダーは正しいので、最初にそれを修正する必要があります。もう 1 つの問題は、改行文字がシステムのデフォルトと同じであると想定していることです。データの取得元やプログラムの実行場所によっては、この仮定が正しくない場合があります。

于 2010-08-18T22:00:24.987 に答える