4

引用の問題がある CSV ファイルがあります。

"Albanese Confectionery","157137","ALBANESE BULK ASST. MINI WILD FRUIT WORMS 2" 4/5LB",9,90,0,0,0,.53,"21",50137,"3441851137","5 lb",1,4,4,$6.7,$6.7,$26.8

SuperCSV は、これらのフルーツ ワームを窒息させています (しゃれが意図されています)。2"がおそらく であるべきであることはわかっていますが2""、そうではありません。LibreOffice は実際にこれを正しく解析します (これには驚きました)。私は自分の小さなパーサーを書くことを考えていましたが、他の行には文字列内にコンマがあります:

"Albanese Confectionery","157230","ALBANESE BULK JET FIGHTERS,ASSORTED 4/5  B",9,90,0,0,0,.53,"21",50230,"3441851230","5 lb",1,4,4,$6.7,$6.7,$26.8

このようなクレイジーなものを処理する Java ライブラリを知っている人はいますか? または、利用可能なすべてのものを試す必要がありますか? それとも、これを自分でハッキングしたほうがいいですか?

4

3 に答える 3

6

正しい解決策は、データを生成した人を見つけて、彼らが問題を解決するまでキーボードで頭を殴ることです。

そのルートを使い果たしたら、市場に出回っている他の CSV パーサーのいくつかを試すことができます。私は過去にOpenCSVを使用して成功しました。

OpenCSV ですぐに問題を解決できない場合でも、コードは非常に読みやすく、Apache ライセンスの下で利用できます。スクラッチ。

于 2013-03-04T21:10:33.000 に答える
1

'フルーツワームの窒息'しゃれの+1-私はそれを読んで私のコーヒーで窒息寸前でした:)

そのCSVを本当に修正できない場合は、独自のTokenizerを提供するだけで済みます(スーパーCSVはそのように非常に柔軟です!)。

通常は独自の実装を作成しますreadColumns()が、トークン化する前に、デフォルトのTokenizerを拡張し、readLine()メソッドをオーバーライドして文字列をインターセプトする(そしてエスケープされていない引用符を修正する)方が迅速です。

ここでは、区切り文字の横や行の先頭/末尾にない引用符はエスケープする必要があると仮定しました。完璧にはほど遠いですが、サンプル入力には機能します。これは好きなように実装できます-私が正規表現を使用するには早すぎました:)

このように、スーパーCSVを変更する必要はまったくありません(プラグインするだけです)。そのため、セルプロセッサやBeanマッピングなどの他のすべての機能も利用できます。

package org.supercsv;
import java.io.IOException;
import java.io.Reader;
import org.supercsv.io.Tokenizer;
import org.supercsv.prefs.CsvPreference;

public class FruitWormTokenizer extends Tokenizer {

  public FruitWormTokenizer(Reader reader, CsvPreference preferences) {
    super(reader, preferences);
  }

  @Override
  protected String readLine() throws IOException {
    final String line = super.readLine();
    if (line == null) {
      return null;
    }

    final char quote = (char) getPreferences().getQuoteChar();
    final char delimiter = (char) getPreferences().getDelimiterChar();

    // escape all quotes not next to a delimiter (or start/end of line)
    final StringBuilder b = new StringBuilder(line);
    for (int i = b.length() - 1; i >= 0; i--) {
      if (quote == b.charAt(i)) {
        final boolean validCharBefore = i - 1 < 0
            || b.charAt(i - 1) == delimiter;
        final boolean validCharAfter = i + 1 == b.length()
            || b.charAt(i + 1) == delimiter;
        if (!(validCharBefore || validCharAfter)) {
          // escape that quote!
          b.insert(i, quote);
        }
      }
    }
    return b.toString();
  }
}

このトークナイザーをCsvReaderのコンストラクターに提供するだけです。

于 2013-03-04T23:17:40.027 に答える
1

ここで自分でも驚いたが、自分でハックすると思う。つまり、行を読み取り、引用符/コンマで分割してトークンを生成するだけで済みます。そうすれば、ロジックを自分に合った方法で調整できます。それほど難しいことではありません。ファイルが壊れているように見えるので、いくつかの既存のソリューションを実行するのはより多くの作業のように見えます.

ただし、LibreOffice が既に正しく解析している場合は、そこからファイルを保存して、より合理的なファイルを生成することはできませんでした。ただし、LibreOffice が推測している可能性があると思われる場合は、トークナイザーを自分で作成してください。

于 2013-03-04T21:15:44.310 に答える