.Csv dosyası virgülle ayrılmış dizeler, virgülle ayrılmış alıntı dizeler veya ikisinin kaotik bir kombinasyonu olabileceği zaman .csv dosyalarını ayrıştırmak zor bir konudur. Bulduğum çözüm, üç olasılıktan herhangi birine izin veriyor.
Bir csv dizesinden bir dizi döndüren ParseCsvRow () adlı bir yöntem oluşturdum. İlk önce çift tırnak üzerindeki dizeyi quotesArray adlı bir diziye bölerek dizedeki çift tırnakları ele alıyorum. Alıntılanan dize .csv dosyaları yalnızca çift tırnak işareti varsa geçerlidir. Bir sütun değerindeki çift tırnak, bir çift çift tırnak ile değiştirilmelidir (Bu, Excel'in yaklaşımıdır). .Csv dosyası bu gereksinimleri karşıladığı sürece, ayırıcı virgüllerin yalnızca çift tırnak çiftlerinin dışında görünmesini bekleyebilirsiniz. Çift tırnak çiftlerinin içindeki virgüller sütun değerinin bir parçasıdır ve .csv bir diziye bölünürken göz ardı edilmelidir.
Yöntemim, yalnızca quotesArray'in çift dizinlerine bakarak çift tırnak çiftlerinin dışındaki virgülleri test edecek. Ayrıca, sütun değerlerinin başındaki ve sonundaki çift tırnak işaretlerini kaldırır.
public static string[] ParseCsvRow(string csvrow)
{
const string obscureCharacter = "ᖳ";
if (csvrow.Contains(obscureCharacter)) throw new Exception("Error: csv row may not contain the " + obscureCharacter + " character");
var unicodeSeparatedString = "";
var quotesArray = csvrow.Split('"'); // Split string on double quote character
if (quotesArray.Length > 1)
{
for (var i = 0; i < quotesArray.Length; i++)
{
// CSV must use double quotes to represent a quote inside a quoted cell
// Quotes must be paired up
// Test if a comma lays outside a pair of quotes. If so, replace the comma with an obscure unicode character
if (Math.Round(Math.Round((decimal) i/2)*2) == i)
{
var s = quotesArray[i].Trim();
switch (s)
{
case ",":
quotesArray[i] = obscureCharacter; // Change quoted comma seperated string to quoted "obscure character" seperated string
break;
}
}
// Build string and Replace quotes where quotes were expected.
unicodeSeparatedString += (i > 0 ? "\"" : "") + quotesArray[i].Trim();
}
}
else
{
// String does not have any pairs of double quotes. It should be safe to just replace the commas with the obscure character
unicodeSeparatedString = csvrow.Replace(",", obscureCharacter);
}
var csvRowArray = unicodeSeparatedString.Split(obscureCharacter[0]);
for (var i = 0; i < csvRowArray.Length; i++)
{
var s = csvRowArray[i].Trim();
if (s.StartsWith("\"") && s.EndsWith("\""))
{
csvRowArray[i] = s.Length > 2 ? s.Substring(1, s.Length - 2) : ""; // Remove start and end quotes.
}
}
return csvRowArray;
}
Yaklaşımımın bir dezavantajı, sınırlayıcı virgüllerini belirsiz bir unicode karakterle geçici olarak değiştirme şeklimdir. Bu karakterin o kadar belirsiz olması gerekir ki .csv dosyanızda asla görünmez. Bununla daha fazla ilgilenmek isteyebilirsiniz.