2012-02-10 7 views
4

私は、InputStreamで動作しているスキャナを設定しています。Java Scanner.nextLine()は改行文字を使用します

私はScanner.nextLine()を使用して各行に進み、各行で正規表現の作業を行っています。

私は基本的に[\w\p{Z}]+?[;\n\r]のような正規表現を使って、その行の最後まで何かを拾い上げるか、セミコロンで区切られた場合はただ一つだけを拾います。私InpustStreamが

abcd; 
xyz 

のように見える場合

ので、それはABCDを拾う;,が、xyzのではないでしょう。

これは、スキャナが.nextLine()関数が呼び出されたときに、何らかの形でテキスト行の最後に改行文字を消費しているためです。誰も私にこの問題を解決する方法を教えてもらえますか?情報の追加点として

は、私の正規表現のために、私はPattern.DOTALL

おかげでパターンをコンパイルしています!

+1

これには正規表現のみを使用する必要がありますか? 'String.split'もこのトリックを行うことができると思われますか? – Marnix

+0

本当に簡単に見つけることができます - 各行で正規表現を停止し、nextLine()が取得しているものを確認してください... – hovanessyan

答えて

5

実際には、問題の原因となっているのは、最後の行の最後に改行を入れようとすることです。 : - /最後の行が改行文字なしで突然終了するのは完全に正しいですが、あなたの正規表現はそれを持つ必要があります。改行をアンカーまたは先読みに置き換えることで修正できるかもしれませんが、これについてもっと簡単な方法があります。

一つは、デフォルトの区切り文字を上書きしnext()持つフィールドを反復することである。

Scanner sc1 = new Scanner("abcd;\nxyz"); 
sc1.useDelimiter("[;\r\n]+"); 
while (sc1.hasNext()) 
{ 
    System.out.printf("%s%n", sc1.next()); 
} 

他方が(デフォルトの区切り文字を使用して)nextLine()と行を反復した後、セミコロンで各ラインを分割することです。

Scanner sc2 = new Scanner("abcd;\nxyz"); 
while (sc2.hasNextLine()) 
for (String item : sc2.nextLine().split(";")) 
{ 
    System.out.printf("%s%n", item); 
} 

スキャナのAPIは、私が今までで働いてきたほとんどの肥大化と直感の一つですが、この二つの重要なポイントを覚えていれば、あなたが大幅にそれを使用しての痛みを軽減することができます:

  1. (あなたが文字列のsplit()で行うように)はないフィールド、デリミタマッチングの観点から考えます。
  2. 最初に対応するhasNextXXX()メソッドを呼び出さずにnextXXX()メソッドの1つを呼び出してはいけません。
2

だから、nextLine()の結果に改行を追加してみませんか?

文字列の境界を表す^または$が正規表現の特殊文字ではありませんか?

+0

これはもっと曖昧な回答ですが、私はそれに同意します。文字列の最後に '\ r'文字を追加することができます。または、完全な文字列の正規表現を行います(スキャナを使用しないでください)。それはすべての行末を返します。 – Marnix

+0

文字列が大きすぎるため、一気に正規表現することができません。 – Derek

1

正規表現文字$は「パターンの終わり」を検出します。あなたがライン文字の終わりを持たないので、最初のセミコロンまですべてを消費するのは簡単です。あなたは通常、それに対処する必要はありません、それはシステム依存なので、その動作の一部として改行文字を消費

[^;]+ 

Scanner:ちょうどセミコロン以外のすべてを消費します。

編集:誰かが指摘したコメントでは、line.split(";")を使用して最初の値を取得できます。これも機能します。

0

正規表現のパターンでは\zを使用して入力の末尾を指定するか、末尾に$を使用できます。さらに、Scanner.nextLine()は、デフォルトで改行文字を除いた行を返します。また、Scannerで使用されている区切り文字を、メソッドの;に変更することもできます。最後に、あなたのパターンは、で判断すると、\p{Z}は文字 'Z'を捕まえるだけなので、あなたの考えをしないかもしれません。

+0

ドキュメントを誤解しています。このリンクを参照してください:http://www.regular-expressions.info/posixbrackets.html – Derek

+0

いいえ、 '\ p {Z}'は純正のUnicodeカテゴリですが、まったく役に立たないだけです。これは '\ p {Zl}'(ラインセパレータ、U + 2028)、 '\ p {Zp}'(パラグラフセパレータ、U + 2029)、 '\ p {Zs}'(スペースセパレータ、[リスト] http://www.fileformat.info/info/unicode/category/Zs/list.htm))、**ではなく、 '\ n'または' \ r'です。人々が実際に行や段落を区切るために使用する文字のUnicodeカテゴリはありません。 –

+0

さて、はい、正規表現マッチングはJavaで行いますか? 'Pattern'を使うとき、Java regexの構文を使うべきではありませんか? – fredo

1

APIは明らかに次の行は、あなたが他の回答では、様々な候補の1つ行うことができます任意の行区切りnextLine()

を削除することを指定します。しかし、スキャナには "パターン"のメソッドがあることにも注意してください。あなたはより多くのトークン

、その後

next(Pattern pattern)またはnext(String pattern)を持っている場合は、上記が真を返した場合にトークンを取得するために見つけることが

hasNext(Pattern pattern)hasNext(String pattern):あなたの正規表現が正しいのであれば、あなたは、次の方法を使用することができます。