-2

Web サービスに送信するために、csv ファイルの内容をさまざまな変数に読み込もうとしています。正常に動作していましたが、今日突然例外が発生しました。

インデックスが配列の範囲外だった:

私は何を間違えましたか?

String sourceDir = @"\\198.0.0.4\e$\Globus\LIVE\bnk.run\URA.BP\WEBOUT\";
// Process the list of files found in the directory. 
string[] fileEntries = Directory.GetFiles(sourceDir);
foreach (string fileName2 in fileEntries)
{
    // read values
    StreamReader st = new StreamReader(fileName2);
    while (st.Peek() >= 0)
    {
        String report1 = st.ReadLine();
        String[] columns = report1.Split(','); //split columns 
        String prnout = columns[0];
        String tinout = columns[1];
        String amtout = columns[2];
        String valdate = columns[3];
        String paydate = columns[4];
        String status = columns[5];
        String branch = columns[6];
        String reference = columns[7];
    }
}
4

4 に答える 4

1

正気を保つために、ここに書かれているさまざまなメモをすべてまとめました。このコードは少しきれいで、いくつかの検証が含まれています。

これを試して:

string dir = @"\\198.0.0.4\e$\Globus\LIVE\bnk.run\URA.BP\WEBOUT\";
foreach (string fileName2 in Directory.GetFiles(dir)) {
    StreamReader st = new StreamReader(fileName2);
    while (!sr.EndOfStream)  {
        string line = sr.ReadLine();
        if (!String.IsNullOrEmpty(line)) {
            string[] columns = line.Split(',');
            if (columns.Length == 8) {
                string prnout = columns[0];
                string tinout = columns[1];
                string amtout = columns[2];
                string valdate = columns[3];
                string paydate = columns[4];
                string status = columns[5];
                string branch = columns[6];
                string reference = columns[7];
            }
        }
    }
}

編集: 他のユーザーがコメントしたように、CSV 形式はテキスト修飾子も受け入れます。これは通常、二重引用符記号 (") を意味します。たとえば、テキスト修飾行は次のようになります。

user,"Hello!",123.23,"$123,123.12",and so on,

このように完全にフォーマットされたファイルがある場合、CSV 解析コードの記述は少し複雑になります。何年にもわたって、不適切な形式の CSV ファイルを解析してきました。事実上すべての単体テストに合格する標準コード スクリプトを作成しましたが、説明するのは面倒です。

/// <summary>
/// Read in a line of text, and use the Add() function to add these items to the current CSV structure
/// </summary>
/// <param name="s"></param>
public static bool TryParseLine(string s, char delimiter, char text_qualifier, out string[] array)
{
    bool success = true;
    List<string> list = new List<string>();
    StringBuilder work = new StringBuilder();
    for (int i = 0; i < s.Length; i++) {
        char c = s[i];

        // If we are starting a new field, is this field text qualified?
        if ((c == text_qualifier) && (work.Length == 0)) {
            int p2;
            while (true) {
                p2 = s.IndexOf(text_qualifier, i + 1);

                // for some reason, this text qualifier is broken
                if (p2 < 0) {
                    work.Append(s.Substring(i + 1));
                    i = s.Length;
                    success = false;
                    break;
                }

                // Append this qualified string
                work.Append(s.Substring(i + 1, p2 - i - 1));
                i = p2;

                // If this is a double quote, keep going!
                if (((p2 + 1) < s.Length) && (s[p2 + 1] == text_qualifier)) {
                    work.Append(text_qualifier);
                    i++;

                    // otherwise, this is a single qualifier, we're done
                } else {
                    break;
                }
            }

            // Does this start a new field?
        } else if (c == delimiter) {
            list.Add(work.ToString());
            work.Length = 0;

            // Test for special case: when the user has written a casual comma, space, and text qualifier, skip the space
            // Checks if the second parameter of the if statement will pass through successfully
            // e.g. "bob", "mary", "bill"
            if (i + 2 <= s.Length - 1) {
                if (s[i + 1].Equals(' ') && s[i + 2].Equals(text_qualifier)) {
                    i++;
                }
            }
        } else {
            work.Append(c);
        }
    }
    list.Add(work.ToString());

    // If we have nothing in the list, and it's possible that this might be a tab delimited list, try that before giving up
    if (list.Count == 1 && delimiter != DEFAULT_TAB_DELIMITER) {
        string[] tab_delimited_array = ParseLine(s, DEFAULT_TAB_DELIMITER, DEFAULT_QUALIFIER);
        if (tab_delimited_array.Length > list.Count) {
            array = tab_delimited_array;
            return success;
        }
    }

    // Return the array we parsed
    array = list.ToArray();
    return success;
}

このアルゴリズムがどれほど複雑であっても、テキスト修飾値内に改行が埋め込まれている CSV ファイルを解析できないことに注意してください。たとえば、次のようになります。

123,"Hi, I am a CSV File!
I am saying hello to you!
But I also have embedded newlines in my text.",2012-07-23

これらを解決するために、Try() 機能を使用してテキスト行を追加し、メイン関数が正しく機能することを確認する複数行パーサーを用意しました。

/// <summary>
/// Parse a line whose values may include newline symbols or CR/LF
/// </summary>
/// <param name="sr"></param>
/// <returns></returns>
public static string[] ParseMultiLine(StreamReader sr, char delimiter, char text_qualifier)
{
    StringBuilder sb = new StringBuilder();
    string[] array = null;
    while (!sr.EndOfStream) {

        // Read in a line
        sb.Append(sr.ReadLine());

        // Does it parse?
        string s = sb.ToString();
        if (TryParseLine(s, delimiter, text_qualifier, out array)) {
            return array;
        }
    }

    // Fails to parse - return the best array we were able to get
    return array;
}
于 2012-07-23T16:36:03.040 に答える
1

私のお金は悪いデータファイルにあります. それが変更された方程式の唯一のものである場合 (つまり、コードを変更していない場合)、それがほぼ唯一の選択肢です。

データ ファイルが長すぎない場合は、ここに投稿してください。

以下のようなものを追加して、無効な列の長さを確認できます。

while (st.Peek() >= 0)
{
    String report1 = st.ReadLine();
    String[] columns = report1.Split(','); //split columns 

    if(columns.Length < 8)
    {
         //Log something useful, throw an exception, whatever.  
         //You have the option to quitely note that there was a problem and 
         //continue on processing the rest of the file if you want.
         continue;
    }

    //working with columns below
}
于 2012-07-23T16:29:39.153 に答える
1

.csv ファイルを見なくても推測するのは難しいですが、私の最初の 1 つは、8 つの列がないことです。

元の .csv ファイルを表示して、例外が発生した場所を教えていただければ簡単です。

編集: データに問題がないと思われる場合は、デバッグして、Visual Studio で分割呼び出しが返す内容を確認することをお勧めします。それは役立つかもしれません

edit2: そして、その処理をループで行っているため、各行に少なくとも 8 列があることを確認してください。

于 2012-07-23T16:28:13.357 に答える
0

csv ファイルに含まれる列数がわからないため、長さをテストする必要がある場合があります。

if (columns.Length == 8) {
     String prnout = columns[0];
     String tinout = columns[1];
     ...
}

空の行 (最後に追加の EOL) が表示されたに違いありませんが、それはそれと同じくらい簡単です。

于 2012-07-23T16:30:14.743 に答える