web-dev-qa-db-ja.com

Scanner()でCSVを読む

私のcsvはSystem.outに読み込まれていますが、スペースのあるテキストは次の行に移動することに気づきました(リターン\ nとして)

これが私のcsvの始まりです:

first,last,email,address 1, address 2
john,smith,[email protected],123 St. Street,
Jane,Smith,[email protected],4455 Roger Cir,apt 2

アプリを実行した後、スペース(アドレス1)を持つセルは次の行にスローされます。

import Java.io.File;
import Java.io.FileNotFoundException;
import Java.util.Scanner;

public class main {

    public static void main(String[] args) {
        // -define .csv file in app
        String fileNameDefined = "uploadedcsv/employees.csv";
        // -File class needed to turn stringName to actual file
        File file = new File(fileNameDefined);

        try{
            // -read from filePooped with Scanner class
            Scanner inputStream = new Scanner(file);
            // hashNext() loops line-by-line
            while(inputStream.hasNext()){
                //read single line, put in string
                String data = inputStream.next();
                System.out.println(data + "***");

            }
            // after loop, close scanner
            inputStream.close();


        }catch (FileNotFoundException e){

            e.printStackTrace();
        }

    }
}

コンソールの結果は次のとおりです。

 first、last、email、address 
 1、address 
 2 
 john、smith、blah @ blah.com、123 
 St。 
ストリート、
ジェーン、スミス、blech @ blech.com、4455 
ロジャー
 Cir、apt 
 2 

スキャナーを間違って使用していますか?

42
coffeemonitor
scanner.useDelimiter(",");

これは動作するはずです。

import Java.io.File;
import Java.io.FileNotFoundException;
import Java.util.Scanner;


public class TestScanner {

    public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new File("/Users/pankaj/abc.csv"));
        scanner.useDelimiter(",");
        while(scanner.hasNext()){
            System.out.print(scanner.next()+"|");
        }
        scanner.close();
    }

}

CSVファイルの場合:

a,b,c d,e
1,2,3 4,5
X,Y,Z A,B

出力は次のとおりです。

a|b|c d|e
1|2|3 4|5
X|Y|Z A|B|
41
Pankaj

エラーのあるCSVパーサーの書き込みを停止してください!

私は何百ものCSVパーサーを見ており、いわゆるtutorialsと呼ばれています。

それらのほぼすべてが間違っています!

これは私には影響しないので、それほど悪いことではありませんが、CSV readersを書き込もうとして間違った人はCSV writersを書きます。また、それらを間違えます。そして、これらのパーサーを作成する必要があります。

CSV(それほど明白ではない順に):

  1. 値を引用符で囲むことができます
  2. 「」以外の引用文字を含めることができます
  3. 「」や「」以外の引用文字を含めることもできます
  4. 引用符を使用することはできません
  5. 一部の値には引用符を使用し、他の値には使用しないこともできます
  6. および以外の区切り文字を使用できます。
  7. 区切り文字と(引用符で囲まれた)値の間に空白を含めることができます
  8. aSCII以外の文字セットを持つことができます
  9. 必要各行に同じ数の値がありますが、常にそうとは限りません
  10. 引用符で囲まれた空のフィールドを含めることができます:"foo","","bar"または"foo",,"bar"
  11. 値に改行を含めることができます
  12. できません区切り文字がない場合、値に改行を含める
  13. できない値の間に改行を含める
  14. 適切にエスケープされている場合、値内に区切り文字を含めることができます
  15. 区切り記号をエスケープするためにバックスラッシュを使用しない.
  16. 引用文字自体を使用してエスケープします。 Frodo's Ring'Frodo''s Ring'になります
  17. 値の最初または最後に引用文字を含めることができます。または、文字のみとして引用することもできます("foo""", """bar", """"
  18. 引用されていない値の中に引用された文字を含めることもできます。これはエスケープされていない

これが問題ではなく明らかだと思われる場合は、もう一度考え直してください。 every single oneのこれらの項目が誤って実装されているのを見てきました。 majorソフトウェアパッケージでも。 (例:Officeスイート、CRMシステム)

すぐに使える、すぐに使えるCSVリーダーとライターがあります。

自分で書くことに固執する場合は、少なくとも(非常に短い) RFC for CSV を読んでください。

142
Scheintod

Scanner.next()は改行を読み取りませんが、空白で区切られた次のトークンを読み取ります(デフォルトでは、useDelimiter()が区切りパターンの変更に使用されなかった場合)。行を読み取るには、Scanner.nextLine()を使用します。

単一の行を読んだら、String.split(",")を使用して行をフィールドに分割できます。これにより、必要な数のフィールドで構成されていない行を識別できます。 useDelimiter(",");を使用すると、ファイルの行ベースの構造が無視されます(各行は、コンマで区切られたフィールドのリストで構成されます)。例えば:

while (inputStream.hasNextLine())
{
    String line = inputStream.nextLine();
    String[] fields = line.split(",");
    if (fields.length >= 4) // At least one address specified.
    {
        for (String field: fields) System.out.print(field + "|");
        System.out.println();
    }
    else
    {
        System.err.println("Invalid record: " + line);
    }
}

既に述べたように、CSVライブラリを使用することをお勧めします。たとえば、これ(およびuseDelimiter(",")ソリューション)は、,文字を含む引用符付き識別子を正しく処理しません。

9
hmjd

既存のCSVライブラリを使用することは、最初からRFC-4180に準拠することをお勧めします。前述のOpenCSVとOster Millerに加えて、他にも一連のCSVライブラリがあります。パフォーマンスに興味がある場合は、 niVocity/csv-parsers-comparison をご覧ください。それはそれを示しています

jDK 6、7、8、または9のいずれかを使用すると、常に最速です。この調査では、これら3つのいずれにもRFC 4180互換性の問題は見つかりませんでした。 OpenCSVとOster Millerの両方が、それらの約2倍遅いことがわかりました。

私は著者とは一切関係ありませんが、uniVocity CSVパーサーに関しては、著者がそのパーサーと同じであるため、研究が偏っている可能性があります。

注目すべきは、SimpleFlatMapperの作成者が パフォーマンス比較 を公開したことです。

1
Yushin Washio

NextLine()を区切り文字(?=([^\"]*\"[^\"]*\")*[^\"]*$)")で分割します。

0
Harsh Mighlani