2013-05-29 6 views
0

Я работаю над программой, которая переформатирует CSV-файлы с помощью C#. Он импортирует CSV и использует определенные столбцы для представления в новом CSV-файле. Используя этот код, я получаю исключение System.IndexOutOfRangeException.System.IndexOutOfRangeException в программе переформатирования CSV

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]. Может ли кто-нибудь помочь мне в этом? Или, может быть, есть другой способ сделать это, что лучше?

Вот весь отладочный вывод:

'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\11.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities.Sync\11.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\11.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'c:\users\daniel\documents\visual studio 2012\Projects\CSVConverter\CSVConverter\bin\Debug\CSVConverter.vshost.exe' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml.Linq\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.Linq.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Data.DataSetExtensions\v4.0_4.0.0.0__b77a5c561934e089\System.Data.DataSetExtensions.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.CSharp\v4.0_4.0.0.0__b03f5f7f11d50a3a\Microsoft.CSharp.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll' 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll' 
The thread 'vshost.NotifyLoad' (0x52c) has exited with code 0 (0x0). 
The thread 'vshost.LoadReference' (0x6cc) has exited with code 0 (0x0). 
'CSVConverter.vshost.exe' (Managed (v4.0.30319)): Loaded 'c:\users\daniel\documents\visual studio 2012\Projects\CSVConverter\CSVConverter\bin\Debug\CSVConverter.exe', Symbols loaded. 
A first chance exception of type 'System.IndexOutOfRangeException' occurred in CSVConverter.exe 
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in CSVConverter.exe 
Additional information: Index was outside the bounds of the array. 
The program '[6952] CSVConverter.vshost.exe: Managed (v4.0.30319)' has exited with code -1073741510 (0xc000013a). 
+0

Не могли бы вы показать нам CSV? –

ответ

0

Чтение текстовых файлов с разделителями не так просто, как это может показаться на первый взгляд.

Если ваш файл с разделителями с запятой имеет 16 столбцов, массив, полученный в результате разделения строки , должен быть иметь длину 16 (это означает, что наибольшее смещение в массиве равно +15). Это может быть меньше, если какой-либо из следующих условий для любой строки в исходных данных:

  1. У вас есть короткая запись в файле.
  2. У вас есть запись, в которой одно поле содержит встроенную пару CR, LF или CR + LF, таким образом, разбивая запись на две (или более) строки и приводя к случаю № 1 выше.

Возможно, вы столкнулись с большим количеством столбцов, чем вы думаете. Основная причина этого заключается в том, что данные, загрязненные нечистотой мира, как бы то ни было, часто нечисты. Люди знали, что они помещают данные с разделителями, такими как запятые или точки с запятой. Когда вы делаете наивный Split() на текст, вы не всегда получаете то, что хотите. И это особенно верно для файлов «CSV», формат которых довольно [cough] свободно. И еще более свободно реализовано.

Возможно, вы захотите посмотреть на Fast CSV Reader от Sebastien Lorion от CodeProject. Он работает достаточно хорошо и заботится о многих неожиданных случаях, с которыми вы можете столкнуться.

Другие ссылки вы можете посмотреть по адресу:

Отредактировано замечено: Библиотека Конгресса, похоже, также вложила в формат CSV: http://www.digitalpreservation.gov/formats/fdd/fdd000323.shtml

+0

Спасибо, особенно за ссылку Fast CSV Reader. Другой парень упомянул библиотеку [FileHelper] (http://filehelpers.sourceforge.net/), которая очень полезна до сих пор и намного проще. К сожалению, этот парень удалил свой ответ. Но я попробую Fast CSV Reader, если файловый сервер не работает. – danielunderwood

1

Вы сказали, что «Импортируемые CSV имеет 16 столбцов, поэтому она должна быть проиндексирована х [17].» это не правильно. Массивы индексируются 0, поэтому, если CSV имеет 16 столбцов, х [15] будет последним столбцом. Любой индекс, превышающий этот параметр, даст исключение за пределы.

EDIT: глядя на ваш код Я заметил, что вы на самом деле не пытаетесь получить доступ к чему-либо за конечным индексом, поэтому первый вопрос, вероятно, не несет ответственности за ваш сбой; вот еще одно предложение. Добавьте некоторые проверки границ. Я бы предположил, что Split в вашем запросе LINQ разбивает неполную строку, а затем вы пытаетесь получить доступ к индексам, которые не существуют (т. Е. Строка содержит только 4 элемента, и ее следует игнорировать, но ваш код просто предполагает, что он имеет 16 и пытается получить доступ к индексу, который выходит за пределы диапазона в строке error'd). Если вы разделите строку и получите доступ к индексам между 0 и n, убедитесь, что длина массива больше n, прежде чем делать это.

0

Возможно, у вас есть дополнительный разрыв строки (особенно в конце файла), который дает пустую строку. Для работы вокруг вы можете изменить ваш where состояние как:

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

Я не уверен, что понял, но я дам ему свой лучший снимок. Если у вас есть 16 элементов в массиве, то индекс последнего элемента в массиве будет x [15], так как массивы в большинстве языков начнут подсчитывать в 0 вместо 1. Индекс первого элемента в массиве равен x [ 0].

Еще одна вещь, которую я могу добавить, заключается в том, что похоже, что вы получаете массив, превращая его в IEnumerable, а затем возвращаете его в массив без использования каких-либо причудливых вещей, которые предоставляет IEnumerable. Вместо этого я бы предложил использовать цикл foreach для этой задачи.

Удачи и, надеюсь, это помогло!

Смежные вопросы