C# CSV重新格式化程序中的System.IndexOutOfRangeException

C# CSV重新格式化程序中的System.IndexOutOfRangeException,c#,debugging,csv,file-io,C#,Debugging,Csv,File Io,我正在开发一个程序,该程序使用C#重新格式化CSV文件。它导入CSV,并使用某些列在新的CSV文件中表示。我正在使用此代码获取System.IndexOutOfRangeException异常 using System; using System.Collections; using System.Linq; class CSVFiles { static void Main(string[] args) { // Create the IEnumerable

我正在开发一个程序,该程序使用C#重新格式化CSV文件。它导入CSV,并使用某些列在新的CSV文件中表示。我正在使用此代码获取System.IndexOutOfRangeException异常

using System;
using System.Collections;
using System.Linq;

class CSVFiles
{
    static void Main(string[] args)
    {
        // Create the IEnumerable data source 
        string[] lines = System.IO.File.ReadAllLines(@"presta.csv");

        // Create the query. Put field 2 first, then 
        // reverse and combine fields 0 and 1 from the old field
        IEnumerable query =
            from line in lines
            let x = line.Split(';')
            select x[0] + ", base, 0, " + x[0] + ", " + x[7] + ", " + x[1] + ", " + x[2] + ", " + x[3] + ", " + x[15] + ", " + x[4] + ", " + x[6] + ", " + x[7] + ", Sí, " + x[12] + ", " + x[12] + ", " + x[12] + ", " + x[12];

        // Execute the query and write out the new file. Note that WriteAllLines 
        // takes a string[], so ToArray is called on the query.
        System.IO.File.WriteAllLines(@"outlet.csv", query.Cast<String>().ToArray());

        Console.WriteLine("outlet.csv written to disk. Press any key to exit");
        Console.ReadKey();
    }
}
你说“导入的CSV有16列,所以应该索引到x[17]”这是错误的。数组的索引为0,因此如果CSV有16列,那么x[15]将是最后一列。任何大于该值的索引都将给出一个越界异常


编辑:查看您的代码,我注意到您实际上没有尝试访问最终索引之外的任何内容,因此第一个问题可能不是导致崩溃的原因;这里还有一个建议。添加一些边界检查。我假设LINQ查询中的
Split
正在拆分一个不完整的行,然后您尝试访问不存在的索引(即该行上只有4个项目,应该忽略,但您的代码只是假设它有16个,并尝试访问错误行中超出范围的索引)。如果拆分一行并要访问介于0和n之间的索引,请检查以确保数组长度大于n,然后再执行此操作。

您可能会有一个额外的换行符(特别是在文件末尾),该换行符会给出一个空字符串。要解决此问题,您可以将
的where
条件修改为:

from line in lines
where !String.IsNullOrEmpty(line)
...

读取带分隔符的文本文件并不像最初显示的那样简单

如果以分号分隔的文件有16列,则拆分一行产生的数组长度应为16(表示数组中的最大偏移量为+15)。如果源数据中的任何一行符合以下任一条件,则该值可能会更小:

  • 文件中有一个简短的记录
  • 您有一个记录,其中一个字段包含嵌入的CR、LF或CR+LF对,因此将该记录拆分为两行(或多行),并导致上述情况#1
  • 你可能会得到比你想象的更多的专栏。其主要原因是数据被世界的不洁所污染,因为它通常是不干净的。众所周知,人们在数据中乱扔分隔符,如逗号或分号。当您对文本执行简单的
    Split()
    操作时,您并不总能得到想要的。对于“CSV”文件尤其如此,其格式的定义相当松散。而且实现更加松散

    你可能想看看用塞巴斯蒂安·洛里恩的。它工作得很好,可以处理很多你们可能遇到的意外情况

    您可能需要查看的其他参考资料:

    • ,逗号分隔值(CSV)文件的通用格式和MIME类型

    编辑说明:国会图书馆似乎也对CSV格式进行了权衡:

    我不确定自己是否理解,但我会尽我最大的努力。如果一个数组中有16个项目,那么数组中最后一个项目的索引将是x[15],因为大多数语言中的数组从0开始计数,而不是从1开始计数。数组中第一项的索引为x[0]

    我要补充的另一件事是,它看起来像是一个数组,将其转换为IEnumerable,然后将其转换回数组,而不使用IEnumerable提供的任何奇特的东西。我建议使用foreach循环来完成这个任务


    祝你好运,希望这有帮助

    你能给我们看一下CSV吗?谢谢,特别是快速的CSV阅读器链接。另一个人提到了图书馆,到目前为止,它非常有用,而且容易得多。不幸的是,那家伙删除了他的答案。但是如果filehelper不起作用,我会尝试快速CSV阅读器。
    from line in lines
    where !String.IsNullOrEmpty(line)
    ...