2017-10-02 9 views
1

このメソッドで問題が発生しています。このメソッドは、一連のデータ(攻撃ID [int]、日付[MM/DD/YYYYの形式で保存された文字列]、モンスター[String]の名前、場所[String]の名前のレポーターのテキストファイルを読み込むはずです。攻撃[String])をコンマで区切り、それらの値をmonsterAttacksというArrayListに入れます。このメソッドを実行するたびに、InputMismatchExceptionが発生します。私はそれが日付と何か関係があると感じているが、私はこの場合String split()メソッドをどこでどのように使うべきか分からない。どのようにしてこの作業を適切に行うことができますか?Javaの読み込みファイルからの文字列

免責事項:これは宿題の一部です。

ありがとうございます。

編集:テキストファイルからのサンプルデータ:

23,12/23/1994、ドラキュラ、カリフォルニア州、トリシャTakinawa

25,11/1992分の12、ゴジラ、ニューヨーク、デビッド

private void readFromFile(){ 
    if(!(monsterAttacks.isEmpty())) { 
     monsterAttacks.clear(); 
     System.out.println("\nList cleared..."); 
    } 
    System.out.println("Enter path: "); 
    String pathName = getUserInput(); 
    File file = new File(pathName); 
    Scanner read; 
    MonsterAttack attack; 

    try { 
     read = new Scanner(file); 
     do { 
      int id = read.nextInt(); 
      String date = read.next(); 
      String name = read.next(); 
      String location = read.next(); 
      String reporter = read.next(); 
      attack = new MonsterAttack(id, date, name, location, reporter); 
      monsterAttacks.add(attack); 
     } while (read.hasNext()); 

     read.close(); 
    } catch(IOException e){ 
     e.printStackTrace(); 
    } 

} 
+0

あなたはファイル内のデータのサンプルを入れてもらえますか? –

+0

@TiagoLunaもちろん。私はちょうどそれを追加した。 –

+0

ありがとう、@ max-orozco。私はあなたの問題を解決するために、ストリーム上の操作だけを使用しました。私の答えをチェックしてください。私はそれが助けて欲しい –

答えて

1

あなたはあなたのデータは

は、カンマで区切られていることを語ってくれた

もしそうなら、これらのトークンセパレータを考慮する必要があります。ここで続行する1つの方法は、単に行全体を読み込み、その後、各用語にアクセスするには、カンマで分割するようになります:

try { 
    read = new Scanner(file); 
    do { 
     String line = read.nextLine(); 
     String[] parts = line.split(",\\s*"); 
     int id = Integer.parseInt(parts[0]); 
     String date = parts[1]; 
     String name = parts[2]; 
     String location = parts[3]; 
     String reporter = parts[4]; 
     attack = new MonsterAttack(id, date, name, location, reporter); 
     monsterAttacks.add(attack); 
    } while (read.hasNext()); 

    read.close(); 
} catch(IOException e){ 
    e.printStackTrace(); 
} 
1

私は非常にこれだけのためにファイルリーダーを使用することをお勧めします、それはuは必要がある場合、すべてを持っており、 Java 8に付属するストリーム・コレクションは、指定された入力に対して実行できる素晴らしい操作を提供します。

final File definitions = Paths.get("some/dir", "monster_definitions.txt").toFile(); 
    final BufferedReader reader = new BufferedReader(new FileReader(definitions)); 

    final String[] entries = reader.lines().collect(Collectors.joining()).split(")"); 

    for(String entry : entries){ 

     final String[] data = entry.substring(1, entry.lastIndexOf(entry)-1).split(","); 

     final int id = Integer.parseInt(data[0]); 
     final String date = data[1]; 
     final String name = data[2]; 
     final String location = data[3]; 
     final String reporter = data[4]; 

     monsterAttacks.add(new MonsterAttack(id, date, name, location, reporter)); 
    } 

    reader.close(); 

今、私たちは最初にすべての行のストリームを取得し、我々は最後に1列にそれぞれ別の行を収集:ここで

はコードです。これは個々のエントリの最後のマークであるため、この文字列を ")"で分割します。次に、各エントリをループし、エントリの部分文字列を返します。インデックス1から最終インデックス-1で終わるインデックスは、 "("と ")"を取り除くためにのみ使用します。これで、定義をキャッシュするために必要なすべての情報を含む未処理のエントリが得られました。 "、"を正規表現として使用してエントリを分割し、個々のデータエントリの配列を取得します。

しかし、この種の定義のシリアル化とデシリアライズでは、JSONとして何かを使用することをお勧めします。これは、作業がはるかに簡単で、データ操作の柔軟性も大幅に向上します。


編集:ちょうどあなたが各エントリのためのスプリッタを持っていなかったことに気づいた。すべてのエントリが改行で分割されていない限り。使用して(あなたのプロジェクトは、Java 8を使用して、あなたは、単に(line()付き)ストリームを使用してファイルのデータを操作し、目的のクラスにマップすることができますことを考えると、 `

final List<String> entries = new ArrayList<>(reader.lines().collect(Collectors.toList())); 

      for(String entry : entries){` 
+0

ストリームを使用する目的は、入力(ファイル)全体を処理してメモリに読み込まないようにすることです。その目的はすぐに '収集'方法を呼び出すことによって取り消されました。これは、monsterAttacks.add(...)の呼び出しで起こることは間違いありませんが、Java 8のストリームパイプラインに最初から最後まで保存する方がいいかもしれません。私はちょうどストリームに続く 'for'ループが適切でないと感じています。 – YoYo

+0

@YoYoストリームから離れることなく必要な操作をすべて実行するのが最も良いと思います。しかし、話題のスターターには、宿題に問題があるようで、ストリームに慣れていなくても少し気になることがあります。特にいくつかの豪華なワンライナーでは:D –

+0

あなたはそれらを呼び出すときに、それらの豪華なワンライナーを書くのではなく、しばしばそうですが、1つのTBファイルをメモリに読み込まないようにするため、第2段階。これは、Apache-sparkのような環境でRDDを使用して作業を開始すると、より重要になります。優れた実践のためのプリンシパル。 1ライナーとして書くことは単なる副作用です。それでもあなたのポイントはポスターの意図の文脈で有効です。 – YoYo

0

:その場合は、uがこのような何かを単に行うことができますmap())、この場合はMonsterAttackです。

public void readFromFile(String path) throws Exception { 
    final File definitions = Paths.get(path).toFile(); 
    final BufferedReader reader = new BufferedReader(new FileReader(definitions)); 

    monsterAttacks = reader.lines().map(line -> { 
     String[] entry = line.split(","); 
     return new MonsterAttack(Integer.parseInt(entry[0]), entry[1], entry[2], entry[3], entry[4]); 
    }).collect(Collectors.toList()); 

    reader.close(); 
} 

私はそれが役に立ちそうです。

0

すでに良い回答が得られていますが、構造化されたアプリケーションの開発を検討している場合には、よりプロフェッショナルなソリューションを指摘したいと思います。

私はこれがかなりオーバーヘッドであることを知っていますが、これは宿題であり、おそらく単純なJavaアプリケーションであることを理解しています。私はこれが将来のための素晴らしい参考資料だと思う。

フラットファイルリーダー/ライターでは、フラットファイルをPOJO(Plain Old Java Object)にマップすることができます。また、Springバッチを使用して操作を結合し、バッチアプリケーションの構造を改善することもできます。ここで

それは(上記のリンクから)どのように動作するかの簡単なスニペット:

@Configuration 
public class CsvFileToDatabaseJobConfig { 

    @Bean 
    ItemReader<StudentDTO> csvFileItemReader() { 
     FlatFileItemReader<StudentDTO> csvFileReader = new FlatFileItemReader<>(); 
     csvFileReader.setResource(new ClassPathResource("data/students.csv")); 
     csvFileReader.setLinesToSkip(1); 
... 
    } 

    private LineMapper<StudentDTO> createStudentLineMapper() { 
     ... 
    } 

    private LineTokenizer createStudentLineTokenizer() { 
     DelimitedLineTokenizer studentLineTokenizer = new DelimitedLineTokenizer(); 
     studentLineTokenizer.setDelimiter(";"); 
     studentLineTokenizer.setNames(new String[]{"name", "emailAddress", "purchasedPackage"}); 
     return studentLineTokenizer; 
    } 

    private FieldSetMapper<StudentDTO> createStudentInformationMapper() { 
     BeanWrapperFieldSetMapper<StudentDTO> studentInformationMapper = new BeanWrapperFieldSetMapper<>(); 
     studentInformationMapper.setTargetType(StudentDTO.class); 
     return studentInformationMapper; 
    } 
} 
関連する問題