0

まず、このようにアップコンバートしたいのは珍しいと思いますが、ご容赦ください。これらのcsvファイルはWebサイトのエクスポートを介して取得し、他の形式で取得するオプションはありません。

さて、質問に移りましょう。

このプロセスを実行する古いコードがあります。基本的に各行を読み取り、,s間の各値を選択します。これは、私が変換したいくつかのサンプルではうまく機能しましたが、与えられたサンプルでの作業になると、いくつかの値が適切ではありませんでした。

Notepad ++でファイルを開いたところ、一部のセル自体にが含まれていることがわかりました,"CSVファイルは、これらのセルをsで囲むことにより、これを回避します。以下の例を参照してください。

これはうまくいくでしょう:

John,Smith,johnsmith@email.com,burgers

ただし、これは次のことを行いません。

John,Smith,johnsmith@email.com,"burgers, french fries"

残念ながら、私のコード(String strar[] = thisLine.split(",");)は、一部のセルにコンマが含まれていることを考慮しておらず、それらを:"burgersや。のような異なる列に分割しますfrench fries"

"sで囲まれたテキストを2つの別々の値ではなく、単一の値として効率的に処理するようにプログラムを取得するにはどうすればよいですか?

私があなたたちのために何か他のものを片付けることができるかどうか私に知らせてください。

助けてくれてありがとう、

ユスティニアヌス

4

4 に答える 4

3

CSV文字を文字ごとに確認し、引用符が発生するたびにトグルを設定するだけです。キックオフの例は次のとおりです。

public static List<List<String>> parseCsv(InputStream input, char separator) 
    throws IOException 
{
    BufferedReader reader = null;
    List<List<String>> csv = new ArrayList<List<String>>();
    try {
        reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
        for (String record; (record = reader.readLine()) != null;) {
            boolean quoted = false;
            StringBuilder fieldBuilder = new StringBuilder();
            List<String> fields = new ArrayList<String>();
            for (int i = 0; i < record.length(); i++) {
                char c = record.charAt(i);
                fieldBuilder.append(c);
                if (c == '"') {
                    quoted = !quoted;
                }
                if ((!quoted && c == separator) || i + 1 == record.length()) {
                    fields.add(fieldBuilder.toString().replaceAll(separator + "$", "")
                        .replaceAll("^\"|\"$", "").replace("\"\"", "\"").trim());
                    fieldBuilder = new StringBuilder();
                }
            }
            csv.add(fields);
        }
    } finally {
        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
    }
    return csv;
}

ただし、さらにいくつかの機能などを備えている可能性のあるサードパーティのJavaCSVAPIを取得することもできます

于 2010-07-12T00:00:27.577 に答える
1

私はこれがあなたの当面の問題を本当に助けないことを知っています、しかし私のアドバイスは:それを全くしないでください。埋め込まれたコンマを処理するだけでうまくいくと、非常に幸運になります。埋め込まれた二重引用符はどうですか?埋め込まれた改行?などなど...

正直なところ?答えは、CSVを解析するライブラリを見つけてそれを使用することです。世界中のほぼすべての開発者が「ああ、CSVはとても単純な形式なので、自分で解析する」というトリックに陥っていると確信しています。私は持っていることを知っいます。

私が人々に紹介するのが大好きな自分のCSVパーサーの問題についての素晴らしい投稿があります(私はそのように残酷です)。これは.NET関連の投稿ですが、それでもあなたの状況に当てはまります。あなたは5のステップ#2までしか行っていないことに注意してください...やるべきことがたくさんあります。

于 2010-07-12T02:03:30.117 に答える
1

なんとか自分の質問に答えることができました。少し検索して、私はこの小さなpdfをここで見つけることができました:

http://www.objectmentor.com/resources/articles/tfd.pdf

そこから、35ページのコードを採用してプログラムを操作することができました。すべてのクレジットはに行きJeff Langr, 2001ます。私がしたのは、Javaの現在の標準のいくつかで動作させることだけでした。

これは、将来この問題が発生する可能性のあるすべての人のためのコードです。

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;

public class CSVReader {

    private BufferedReader reader;
    private String line;
    private static final String DOUBLE_QUOTE = "\"";
    private static final String COMMENT_SYMBOL = "#";
    private static final char stateINIT = 'S';
    private static final char stateCOMMENT = '#';
    private static final char stateQUOTED_DATA = 'q';
    private static final char stateQUOTE_IN_QUOTED_DATA = 'Q';
    private static final char stateDATA = 'D';
    private static final char stateNEW_TOKEN = 'N';
    private static final char stateWHITESPACE = 'W';

    public CSVReader(String filename) throws IOException {
        reader = new BufferedReader(new java.io.FileReader(filename));
        loadNextNonCommentLine();
    }

    public ArrayList<String> next() throws IOException {
        if (line == null)
            throw new IOException("Read past end of file");
        ArrayList<String> columns = columnsFromCSVRecord(line);
        loadNextNonCommentLine();
        return columns;
    }

    public boolean hasNext() {
        return line != null;
    }

    void loadNextNonCommentLine() throws IOException {
        do
            line = reader.readLine();
        while (line != null && line.startsWith(COMMENT_SYMBOL));
        if (line == null)
            reader.close();
    }

    public ArrayList<String> columnsFromCSVRecord(String line) throws IOException {
        char state = stateINIT;
        char ch;
        int i = 0;
        ArrayList<String> tokens = new ArrayList<String>();
        StringBuffer buffer = new StringBuffer();
        char[] charArray = line.toCharArray();
        while (i < charArray.length) {
            ch = charArray[i++];
            switch (state) {
            case stateINIT:
                switch (ch) {
                case '"':
                    buffer.append(ch);
                    state = stateQUOTED_DATA;
                    break;
                case ',':
                    state = stateNEW_TOKEN;
                    tokens.add(clean(buffer));
                    buffer = new StringBuffer();
                    break;
                case '\t':
                case ' ':
                    break;
                case '#':
                    state = stateCOMMENT;
                    break;
                default:
                    state = stateDATA;
                    buffer.append(ch);
                    break;
                }
                break;
            case stateCOMMENT:
                break;
            case stateQUOTED_DATA:
                switch (ch) {
                case '"':
                    buffer.append(ch);
                    state = stateQUOTE_IN_QUOTED_DATA;
                    break;
                default:
                    buffer.append(ch);
                    break;
                }
                break;
            case stateQUOTE_IN_QUOTED_DATA:
                switch (ch) {
                case '"':
                    state = stateQUOTED_DATA;
                    break;
                case ',':
                    state = stateNEW_TOKEN;
                    tokens.add(clean(buffer));
                    buffer = new StringBuffer();
                    break;
                case ' ':
                case '\t':
                    break;
                case '#':
                    tokens.add(clean(buffer));
                    state = stateCOMMENT;
                    break;
                default:
                    throw new IOException("badly formed CSV record:" + line);
                }
                break;
            case stateDATA:
                switch (ch) {
                case '#':
                    tokens.add(clean(buffer));
                    state = stateCOMMENT;
                    break;
                case ',':
                    state = stateNEW_TOKEN;
                    tokens.add(clean(buffer));
                    buffer = new StringBuffer();
                    break;
                default:
                    buffer.append(ch);
                    break;
                }
                break;
            case stateNEW_TOKEN:
                switch (ch) {
                case '#':
                    tokens.add(clean(buffer));
                    state = stateCOMMENT;
                    break;
                case ',':
                    tokens.add(clean(buffer));
                    buffer = new StringBuffer();
                    break;
                case ' ':
                case '\t':
                    state = stateWHITESPACE;
                    break;
                case '"':
                    buffer.append(ch);
                    state = stateQUOTED_DATA;
                    break;
                default:
                    state = stateDATA;
                    buffer.append(ch);
                    break;
                }
                break;
            case stateWHITESPACE:
                switch (ch) {
                case '#':
                    state = stateCOMMENT;
                    break;
                case ',':
                    state = stateNEW_TOKEN;
                    // ACCEPT NEW EMPTY COLUMN HERE??
                    break;
                case '"':
                    buffer.append(ch);
                    state = stateQUOTED_DATA;
                    break;
                case ' ':
                case '\t':
                    break;
                default:
                    state = stateDATA;
                    buffer.append(ch);
                    break;
                }
                break;
            default:
                break;
            }
        }
        if (state == stateQUOTED_DATA)
            throw new IOException("Unmatched quotes in line:\n" + line);
        if (state != stateCOMMENT)
            tokens.add(clean(buffer));
        return tokens;
    }

    public String clean(StringBuffer buffer) {
        String string = buffer.toString().trim();
        if (string.startsWith(DOUBLE_QUOTE))
            return string.substring(1, string.length() - 1);
        return string;
    }
}
于 2010-07-12T03:06:07.503 に答える
0

split()に依存するのではなく、この状況を処理するための独自のパーサーを作成します。「」または「」のペアの間のすべての文字を単一のトークンとして文法に処理させます。

于 2010-07-11T23:53:13.397 に答える