我试图将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];
}
}
答案 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),这就是那么简单