越界错误c#

时间:2012-07-23 16:25:05

标签: c# .net

我试图将csv文件的内容读入不同的变量以便发送到Web服务。它一直工作正常但突然今天我得到了例外。

索引超出了数组的范围:

我做错了什么?

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 个答案:

答案 0 :(得分:2)

我的钱是坏数据文件。如果这是方程式中唯一已经改变的东西(也就是说你没有做任何代码更改),那么这几乎是你唯一的选择。

如果您的数据文件在此处发布的时间不会太长,我们可以肯定地告诉您。

您可以添加以下内容来检查无效的列长度:

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
}

答案 1 :(得分:1)

即使没有看到.csv文件也难以猜测,但我的第一个就是你没有8列。

如果您能够显示原始.csv文件,并告诉我们异常弹出的位置会更容易。

编辑:如果您认为数据没问题,我建议您调试并查看拆分调用在Visual Studio中返回的内容。这可能会有所帮助

edit2:因为你在循环中进行处理,所以确保每行至少有8列。

答案 2 :(得分: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()功能添加额外的文本行来验证main函数是否正常工作:

/// <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;
}

答案 3 :(得分:0)

由于您不知道csv文件中有多少列,您可能需要测试长度:

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

我打赌你只是得到一个空行(最后的额外EOL),这就是那么简单