15

約行以上の大きCSVTSV(タブ区切りの)ファイルを読み込もうとしています。今、私はを含む行1000000を読み込もうとしましたが、それは私に。をスローします。行のある小さなファイルで動作します。だから私は巨大なファイルの読み取りをサポートするものが他にあるかどうか疑問に思いました。あなたはなにか考えはありますか?TSV~2500000opencsvjava.lang.NullPointerExceptionTSV~250000LibrariesCSVTSV

私のコードに興味のある人は誰でも(私はそれを短くしているので、Try-Catch明らかに無効です):

InputStreamReader in = null;
CSVReader reader = null;
try {
    in = this.replaceBackSlashes();
    reader = new CSVReader(in, this.seperator, '\"', this.offset);
    ret = reader.readAll();
} finally {
    try {
        reader.close();
    } 
}

編集:これは私が:を構築する方法InputStreamReaderです

private InputStreamReader replaceBackSlashes() throws Exception {
        FileInputStream fis = null;
        Scanner in = null;
        try {
            fis = new FileInputStream(this.csvFile);
            in = new Scanner(fis, this.encoding);
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            while (in.hasNext()) {
                String nextLine = in.nextLine().replace("\\", "/");
                // nextLine = nextLine.replaceAll(" ", "");
                nextLine = nextLine.replaceAll("'", "");
                out.write(nextLine.getBytes());
                out.write("\n".getBytes());
            }

            return new InputStreamReader(new ByteArrayInputStream(out.toByteArray()));
        } catch (Exception e) {
            in.close();
            fis.close();
            this.logger.error("Problem at replaceBackSlashes", e);
        }
        throw new Exception();
    }
4

4 に答える 4

16

TSV入力の解析にCSVパーサーを使用しないでください。たとえば、TSVに引用文字を含むフィールドがある場合は壊れます。

uniVocity-parsersにはTSVパーサーが付属しています。問題なく10億行を解析できます。

TSV入力を解析する例:

TsvParserSettings settings = new TsvParserSettings();
TsvParser parser = new TsvParser(settings);

// parses all rows in one go.
List<String[]> allRows = parser.parseAll(new FileReader(yourFile));

入力が大きすぎてメモリに保持できない場合は、次のようにします。

TsvParserSettings settings = new TsvParserSettings();

// all rows parsed from your input will be sent to this processor
ObjectRowProcessor rowProcessor = new ObjectRowProcessor() {
    @Override
    public void rowProcessed(Object[] row, ParsingContext context) {
        //here is the row. Let's just print it.
        System.out.println(Arrays.toString(row));
    }
};
// the ObjectRowProcessor supports conversions from String to whatever you need:
// converts values in columns 2 and 5 to BigDecimal
rowProcessor.convertIndexes(Conversions.toBigDecimal()).set(2, 5);

// converts the values in columns "Description" and "Model". Applies trim and to lowercase to the values in these columns.
rowProcessor.convertFields(Conversions.trim(), Conversions.toLowerCase()).set("Description", "Model");

//configures to use the RowProcessor
settings.setRowProcessor(rowProcessor);

TsvParser parser = new TsvParser(settings);
//parses everything. All rows will be pumped into your RowProcessor.
parser.parse(new FileReader(yourFile));

開示:私はこのライブラリの作者です。オープンソースで無料です(Apache V2.0ライセンス)。

于 2014-11-23T08:38:33.193 に答える
7

私はそれを試していませんが、以前にsuperCSVを調査しました。

http://sourceforge.net/projects/supercsv/

http://supercsv.sourceforge.net/

それがあなたのために働くかどうかを確認してください、250万行。

于 2012-12-14T13:56:12.660 に答える
1

によって提案されているようにライブラリを切り替えてみてくださいSatish。それでも問題が解決しない場合は、ファイル全体をトークンに分割して処理する必要があります。

CSVカンマのエスケープ文字がなかったと思います

// r is the BufferedReader pointed at your file
String line;
StringBuilder file = new StringBuilder();
// load each line and append it to file.
while ((line=r.readLine())!=null){
    file.append(line);
}
// Make them to an array
String[] tokens = file.toString().split(",");

その後、それを処理することができます。トークンを使用する前に、トークンをトリミングすることを忘れないでください。

于 2012-12-14T13:59:08.710 に答える
1

その質問がまだアクティブであるかどうかはわかりませんが、これが私がうまく使用している質問です。ただし、StreamやIterableなどのより多くのインターフェースを実装する必要がある場合があります。

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

/** Reader for the tab separated values format (a basic table format without escapings or anything where the rows are separated by tabulators).**/
public class TSVReader implements Closeable 
{
    final Scanner in;
    String peekLine = null;

    public TSVReader(InputStream stream) throws FileNotFoundException
    {
        in = new Scanner(stream);
    }

    /**Constructs a new TSVReader which produces values scanned from the specified input stream.*/
    public TSVReader(File f) throws FileNotFoundException {in = new Scanner(f);}

    public boolean hasNextTokens()
    {
        if(peekLine!=null) return true;
        if(!in.hasNextLine()) {return false;}
        String line = in.nextLine().trim();
        if(line.isEmpty())  {return hasNextTokens();}
        this.peekLine = line;       
        return true;        
    }

    public String[] nextTokens()
    {
        if(!hasNextTokens()) return null;       
        String[] tokens = peekLine.split("[\\s\t]+");
//      System.out.println(Arrays.toString(tokens));
        peekLine=null;      
        return tokens;
    }

    @Override public void close() throws IOException {in.close();}
}
于 2014-04-02T12:44:40.310 に答える