web-dev-qa-db-ja.com

Java区切り文字タブ「\ t」で分割を使用した文字列解析

タブ区切りの文字列を処理しています。 split関数を使用してこれを達成していますが、ほとんどの状況で機能します。この問題は、フィールドが欠落しているときに発生するため、そのフィールドでnullを取得する代わりに、次の値を取得します。解析した値を文字列配列に格納しています。

String[] columnDetail = new String[11];
columnDetail = column.split("\t");

任意の助けをいただければ幸いです。可能であれば、解析された文字列を文字列配列に保存して、解析されたデータに簡単にアクセスできるようにします。

34
lakhaman

String.split正規表現 を使用します。また、スプリットに追加の配列を割り当てる必要もありません。

split-methodはリストを提供します。、問題はタブのオカレンス数を事前に定義しようとすることですが、どうやってそれを知っているのでしょうか? ScannerまたはStringTokenizerを使用してみて、文字列の分割の仕組みを学びましょう。

\ tが機能しない理由、および_\\\\_をエスケープするために_\\_が必要な理由を説明させてください。

さて、Splitを使用するときは、実際には正規表現(正規表現)を取り、正規表現ではどの文字で分割するかを定義したい、そして実際に_\t_を意味しない\ tを書くと分割したいのは_\t_ですよね?したがって、_\t_と書くだけで、正規表現プロセッサに「エスケープされた文字で分割されたt」[〜#〜] not [〜#〜]「ちょっと_\t_のように見えるすべての文字で分割します。」違いに気づきましたか? \を使用すると、何かをエスケープすることを意味します。そして、正規表現の_\_は、あなたが考えているものとは全く異なるものを意味します。

これが、これを使用する必要がある理由ですSolution

_\\t
_

正規表現プロセッサに\ tを探すように指示します。さて、なぜ2つのemが必要なのでしょうか?さて、最初の\は2番目をエスケープします。つまり、テキストを処理しているときは\ tのようになります。

今、あなたが\を分割しようとしているとしましょう

それでは、\\のままになりますが、それは機能しません! \は前の文字をエスケープしようとするからです!そのため、出力を\\にしたいので、\\\\が必要です。

上記の例が、ソリューションが機能しない理由と他のソリューションを征服する方法を理解するのに役立つことを本当に願っています!

さて、私はあなたにこれを与えました answer 前に、多分あなたはそれらを今見始めるべきです。

その他の方法

StringTokenizer

StringTokenizer を調べる必要があります。このタイプの作業には非常に便利なツールです。

_ StringTokenizer st = new StringTokenizer("this is a test");
 while (st.hasMoreTokens()) {
     System.out.println(st.nextToken());
 }
_

これは出力されます

_ this
 is
 a
 test
_

StringTokenizerの2番目のコンストラクターを使用して、区切り文字を設定します。

StringTokenizer(String str, String delim)

スキャナー

Scanner を使用することもできます

_ String input = "1 fish 2 fish red fish blue fish";

 Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");

 System.out.println(s.nextInt());
 System.out.println(s.nextInt());
 System.out.println(s.next());
 System.out.println(s.next());

 s.close(); 
_

出力は次のようになります

_ 1
 2
 red
 blue 
_

つまり、「魚」という単語を切り取り、残りを提供し、「魚」を区切り文字として使用します。

Java API からの例

84
Filip Ekberg

これを試して:

String[] columnDetail = column.split("\t", -1);

Split-functionのlimitパラメーターに関する説明については、 String.split(Java.lang.String、int) のJavadocを読んでください。

split

public String[] split(String regex, int limit)
Splits this string around matches of the given regular expression.
The array returned by this method contains each substring of this string that is terminated by another substring that matches the given expression or is terminated by the end of the string. The substrings in the array are in the order in which they occur in this string. If the expression does not match any part of the input then the resulting array has just one element, namely this string.

The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.

The string "boo:and:foo", for example, yields the following results with these parameters:

Regex   Limit   Result
:   2   { "boo", "and:foo" }
:   5   { "boo", "and", "foo" }
:   -2  { "boo", "and", "foo" }
o   5   { "b", "", ":and:f", "", "" }
o   -2  { "b", "", ":and:f", "", "" }
o   0   { "b", "", ":and:f" }

最後のいくつかのフィールド(私はあなたの状況です)が欠落している場合、次のような列が表示されます。

field1\tfield2\tfield3\t\t

Split()に制限が設定されていない場合、制限は0になり、「末尾の空の文字列は破棄されます」になります。したがって、{"field1"、 "field2"、 "field3"}の3つのフィールドだけを取得できます。

Limitが-1に設定されている場合、非正の値、末尾の空の文字列は破棄されません。したがって、最後の2つが空の文字列である5つのフィールド{"field1"、 "field2"、 "field3"、 ""、 ""}を取得できます。

20
Happy3

誰も答えませんでした-これは部分的には質問のせいです:入力文字列には11個のフィールドが含まれています(これは推測できます)が、タブはいくつありますか?ほとんどの場合exactly 10。

String s = "\t2\t\t4\t5\t6\t\t8\t\t10\t";
String[] fields = s.split("\t", -1);  // in your case s.split("\t", 11) might also do
for (int i = 0; i < fields.length; ++i) {
    if ("".equals(fields[i])) fields[i] = null;
}
System.out.println(Arrays.asList(fields));
// [null, 2, null, 4, 5, 6, null, 8, null, 10, null]
// with s.split("\t") : [null, 2, null, 4, 5, 6, null, 8, null, 10]

フィールドにタブが含まれている場合、これはもちろん期待どおりに機能しません。
-1は、パターンを必要な回数適用することを意味します。したがって、末尾のフィールド(11番目)は保持されます(空の文字列("")として、明示的にnullになりました)。

一方、欠落しているフィールドのタブがない場合-"5\t6"はフィールド5,6のみを含む有効な入力文字列です-fields[]を分割で取得する方法はありません。

6
Mr_and_Mrs_D

String.split実装には、タブ区切りフィールド自体のデータに改行、タブ、および場合によっては "文字が含まれる場合、重大な制限があります。

TABで区切られた形式はロバの時代から存在していましたが、形式は標準化されておらず、さまざまです。多くの実装では、フィールド内に表示される文字(改行とタブ)をエスケープしません。むしろ、CSVの規則に従い、重要でないフィールドは「二重引用符」でラップします。次に、二重引用符のみをエスケープします。したがって、「ライン」は複数のラインにまたがることができます。

周りを読んで、「Apacheツールを再利用するだけ」と聞いたのですが、これは良いアドバイスのようです。

最終的に、私は個人的に opencsv を選択しました。軽量であり、エスケープ文字と引用文字のオプションが用意されているため、最も一般的なカンマ区切りとタブ区切りのデータ形式をカバーできます。

例:

CSVReader tabFormatReader = new CSVReader(new FileReader("yourfile.tsv"), '\t');
5
Luke Usherwood

私はちょうど同じ質問をして、ある種のチュートリアルで答えに気づきました。一般に、分割方法の2番目の形式を使用する必要があります。

split(regex, limit)

完全なチュートリアルはこちら http://www.rgagnon.com/javadetails/Java-0438.html

Limitパラメーターに負の数を設定すると、実際の値が欠落している配列内の空の文字列を取得します。これを使用するには、初期文字列に区切り文字の2つのコピーが必要です。つまり、値が欠落している\ t\tが必要です。

お役に立てれば :)

1
Ivan Marinov

Yourstring.split( "\ x09");を使用できます。私はそれをテストしましたが、動作します。

0
RickeyShao