0

解析する必要がある 2.6GB のセミ csv ファイルがあります。セミ csv とは、(data,data2,data3,...),(moredata,moredata2,moredata3,...),(...) の形式であることを意味します。これは、改行の代わりに "),(" によって新しい行が形成されることを意味します (これは、基本的にファイル全体が 1 行であることを意味します)。

私の計画は、ファイルを読み込んで「)、(」で分割することでした。その後、必要に応じて各要素を解析できました。明らかに、C# には「メモリ不足」の問題がありますが、ファイルを分割することはできません。分割によってデータが誤って分割されないことを保証できないためです。

4

1 に答える 1

0

完全にテストされていないため、文字列は"mystring". 文字列のエスケープはサポートされていません。in 文字列のエスケープはサポートされていません"。したがって、これらは有効ではありませ"my""quote""my\"quote"。ファイルは完全でなければなりません: 末尾に eof がなく、末尾に改行がなく、文字列内以外にスペースがなく、文字列内以外に改行がありません。文字列内では、"(文字列の末尾を示す) 要素以外のすべての要素、要素が多すぎる行、要素が少なすぎる行、null処理なし (技術的には、文字列の a,,は、エラーがスローされずに空の文字列を返します) 以外は何もありません。でサポートされているすべてのタイプがサポートされConvert.ChangeTypeています。

使用法:

using (var fs = new StreamReader("myfile.txt"))
{
    foreach (var objs in ParseStream(sr, new Type[] { typeof(int), typeof(double), typeof(string) }, CultureInfo.InvariantCulture))
    {
        // objs is an object[] where each member is of the type asked 
        // when ParseStream was called
    }
}

コード

public static IEnumerable<object[]> ParseStream(TextReader tr, Type[] types, IFormatProvider culture = null)
{
    var parts = new List<string>();
    var sb = new StringBuilder();

    State state = State.WaitingForOpenBracket;

    long col = -1;
    long row = 0;

    int read;

    while ((read = tr.Read()) != -1)
    {
        col++;

        char ch = (char)read;

        if (ch == '\n')
        {
            col = 0;
            row++;
        }
        else
        {
            col++;
        }

        switch (state)
        {
            case State.WaitingForOpenBracket:
                if (ch != '(')
                {
                    throw new Exception(string.Format("Malformed begin-of-the-row at R: {0}, C: {1}, char: {2}", row, col, ch));
                }

                state = State.WaitingForData;

                break;

            case State.WaitingForData:
            case State.WaitingForColumnSeparator:
                if (ch == ',' || ch == ')')
                {
                    parts.Add(sb.ToString());

                    sb.Clear();

                    if (parts.Count > types.Length)
                    {
                        throw new Exception(string.Format("Too many parts starting at R: {0}, C: {1}", row, col));
                    }

                    if (ch == ')')
                    {
                        var parts2 = parts.Select((p, ix) => Convert.ChangeType(p, types[ix], culture ?? CultureInfo.InvariantCulture)).ToArray();
                        parts.Clear();                                

                        yield return parts2;

                        state = State.WaitingForRowSeparator;
                    }
                }
                else
                {
                    if (state == State.WaitingForColumnSeparator)
                    {
                        throw new Exception(string.Format("Malformed column separator at R: {0}, C: {1}, char: {2}", row, col, ch));
                    }

                    if (ch == '"')
                    {
                        if (sb.Length != 0)
                        {
                            throw new Exception(string.Format("Malformed string at R: {0}, C: {1}, char: {2}", row, col, ch));
                        }

                        state = State.WaitingForEndQuotes;
                    }
                    else
                    {
                        sb.Append(ch);
                    }
                }

                break;

            case State.WaitingForEndQuotes:
                if (ch == '"')
                {
                    state = State.WaitingForColumnSeparator;
                }
                else
                {
                    sb.Append(ch);
                }

                break;

            case State.WaitingForRowSeparator:
                if (ch != ',')
                {
                    throw new Exception(string.Format("Malformed row separator at R: {0}, C: {1}, char: {2}", row, col, ch));
                }

                state = State.WaitingForOpenBracket;

                break;
        }
    }

    if (state != State.WaitingForRowSeparator)
    {
        throw new Exception(string.Format("Malformed end-of-file at R: {0}, C: {1}", row, col));
    }
}
于 2013-08-15T07:40:15.850 に答える