2009-06-18 5 views
2

私はファイルを1行ずつ読み込み、その行を出力したいと思っています。 これを正規表現で解決したいと思います。java regex line

while (...) 
{ 
    private static java.util.regex.Pattern line = java.util.regex.Pattern.compile(".*\\n"); 
    System.out.print(scanner.next(line)); 
} 

InputMismatchExceptionが発生するため、コードの正規表現が正しくありません。 私はこの正規表現で2時間働いています。それで助けてください。

regex powertoyでは、「。* \ n」が正しいことがわかります。しかし、私のプログラムは正しく動作しません。

全体の源である:

/** 
* Extracts the points in the standard input in off file format to the standard output in ascii points format. 
*/ 

import java.util.regex.Pattern; 
import java.util.Scanner; 

class off_to_ascii_points 
{ 
    private static Scanner scanner = new Scanner(System.in);  
    private static Pattern fat_word_pattern = Pattern.compile("\\s*\\S*\\s*"); 
    private static Pattern line = Pattern.compile(".*\\n", Pattern.MULTILINE); 

    public static void main(String[] args) 
    { 
     try 
     { 
      scanner.useLocale(java.util.Locale.US); 

        /* skip to the number of points */ 
      scanner.skip(fat_word_pattern); 

      int n_points = scanner.nextInt(); 

        /* skip the rest of the 2. line */ 
      scanner.skip(fat_word_pattern); scanner.skip(fat_word_pattern); 

      for (int i = 0; i < n_points; ++i) 
      { 
        System.out.print(scanner.next(line)); 
         /* 
         Here my mistake is. 
         next() reads only until the delimiter, 
         which is by default any white-space-sequence. 
         That is next() does not read till the end of the line 
         what i wanted. 

         Changing "next(line)" to "nextLine()" solves the problem. 
         Also, setting the delimiter to line_separator 
         right before the loop solves the problem too. 
         */ 
      } 

     } 
     catch(java.lang.Exception e) 
     { 
      System.err.println("exception"); 
      e.printStackTrace(); 
     } 
    } 
} 

例えば入力の開始である:

OFF 
4999996 10000000 0 
-28.6663 -11.3788 -58.8252 
-28.5917 -11.329 -58.8287 
-28.5103 -11.4786 -58.8651 
-28.8888 -11.7784 -58.9071 
-29.6105 -11.2297 -58.6101 
-29.1189 -11.429 -58.7828 
-29.4967 -11.7289 -58.787 
-29.1581 -11.8285 -58.8766 
-30.0735 -11.6798 -58.5941 
-29.9395 -11.2302 -58.4986 
-29.7318 -11.5794 -58.6753 
-29.0862 -11.1293 -58.7048 
-30.2359 -11.6801 -58.5331 
-30.2021 -11.3805 -58.4527 
-30.3594 -11.3808 -58.3798 

Iは、第1の点の座標を含む行の数である数4999996にスキップ。これらの行は、私が出力に書き込もうとしていることです。

答えて

4

私は期待どおりのコードが動作しないのはなぜ

private static Pattern line = Pattern.compile(".*"); 

scanner.useDelimiter("[\\r\\n]+"); // Insert right before the for-loop 

System.out.println(scanner.next(line)); //Replace print with println 

を使用することをお勧め:

これは、スキャナの使用するクラスとどのようにそのクラスの動作に関係しています。

Javadocの状態:

スキャナは デフォルトで空白と一致する区切りパターンを使用してトークン にその入力を破ります。

つまり、Scanner's.next *メソッドの1つを呼び出すと、スキャナは次の区切り文字が見つかるまで指定された入力を読み取ります。

次の行

-28.6663 -11.3788 -58.8252 

を読んscanner.next(line)開始するだからあなたの最初の呼び出しと-28.6663後のスペースで停止します。次に、トークン(-28.6663)があなたの提供されたパターン(。* \ n)と一致していない(-28.6663)と一致するかどうかを確認します。それが理由です。

+0

コードが失敗する理由を説明するセクションを追加してください – jitter

0

Patternを複数モードに切り替える必要があります。

line = Pattern.compile("^.*$", Pattern.MULTILINE); 
System.out.println(scanner.next(line)); 
+0

MULTILINEも機能しません。 new_line文字を一致する文字列に含めるには、$文字で十分ではありません。 – libeako

0

デフォルトでは、スキャナは区切り文字として空白を使用します。最初のスキップ後に行を読み取る前に、区切り文字を新しい行に変更する必要があります。変更する必要のあるコードは、forループの前に次の行を挿入することです:

scanner.useDelimiter(Pattern.pile(System.getProperty( "line.separator"))));

と、次のようなパターンの変数ライン更新:

プライベート静的パターン線= Pattern.compile( "*" を、パターン。マルチライン);

+0

"line.separator"プロパティは信頼されていません。任意のファイルは、任意のスタイルの行区切り文字を使用することも、2つ以上のスタイルの組み合わせを使用することもできます。スキャナのhasNextLine()メソッドとnextLine()メソッドは、これを考慮に入れます。 –

1

ファイルを標準出力にのみ印刷する場合は、なぜ正規表現を使いたいのですか?あなたが常に最初の2行をスキップしたいと知っているなら、それを達成するためのより簡単な方法があります。

import java.util.Scanner; 
import java.io.File; 

public class TestClass { 
    public static void main(String[] args) throws Exception { 
     Scanner in=new Scanner(new File("test.txt")); 
     in.useDelimiter("\n"); // Or whatever line delimiter is appropriate 
     in.next(); in.next(); // Skip first two lines 
     while(in.hasNext()) 
      System.out.println(in.next()); 
    } 
} 
+0

私は行数を読みなければなりません。これは、2.行の最初の単語です。 – libeako

0

ありがとうございました。

は、今私は私のミスを理解する:

APIドキュメント状態、ScannerクラスのすべてのnextT()メソッドは、最初の区切りパターンをスキップしていること、それはT値を読み取ろうとします。しかし、各next ...()メソッドはデリミタの最初の出現までしか読み込まないと言うのは忘れてしまいます!