近期都在處理淘寶商品數據包識別問題,滿以為CSV文件就是以行為分割,以逗號為字段分割的文件體系。
自己在編寫處理程序時,增加了2個參數: 第一個,字符集,第二,告知處理方法,文件的列在第幾行。
同時,對某些生成出來的數據包不規據的,例如生成出2個同名列的,等等文件,做了一定的容錯。
滿以為這樣就OK了,沒想到,老革命遇上新問題。原來 CSV文件中還是有轉義的,引號即是。這一個處理,導致
程序出現了嚴重BUG,有一批數據包無法識別。。。。
現程序已經優化過。本CSV閱讀程序,直接將CSV文件轉換成TABLE格式,可以識別引號,可以識別在字符串中的回車,比一般網上查找的CSV文件
閱讀程序要好,我試過,基本和WPS(我機器上沒裝OFFICE)容錯能力一致。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace test
{
public class JHCSV
{
public static DataTable LoadCsv(string filename, System.Text.Encoding encoder, char pfix, int headerLineIndex)
{
List<string> dataList = getData(filename, encoder);
DataTable dt = Getdt(dataList, headerLineIndex, pfix);
for (int i = headerLineIndex + 1; i < dataList.Count; i++)
{
if (dataList[i].Trim().Equals(""))
{
continue;
}
else
{
DataRow dr = dt.NewRow();
ReadLine(ref dr, dataList[i], pfix);
dt.Rows.Add(dr);
}
}
return dt;
}
private static DataRow ReadLine(ref DataRow dr, string line, char pfix)
{
string[] data = line.Split(new char[] { pfix });
StringBuilder ValueBuffer = new StringBuilder("");
int columnIndex = 0;
foreach (string str in data)
{
ValueBuffer.Append(str);
if (checkyh(ValueBuffer.ToString(), '"'))
{
ValueBuffer = ValueBuffer.Replace("\"\"", "\"");
if (columnIndex < dr.Table.Columns.Count)
{
dr[columnIndex] = ValueBuffer.ToString().TrimStart('"').TrimEnd('"');
columnIndex++;
ValueBuffer.Clear();
}
else
{
Console.WriteLine(ValueBuffer.ToString());
ValueBuffer.Clear();
continue;
}
}
else
{
ValueBuffer.Append(pfix);
}
}
return dr;
}
private static DataTable Getdt(List<string> data, int headIndex, char pfix)
{
DataTable dt = new DataTable();
string[] columns = data[headIndex].Split(new char[] { pfix });
foreach (string columnname in columns)
{
if (columnname.Equals(""))
{
continue;
}
else
{
if (dt.Columns[columnname] != null)
{
dt.Columns.Add(columnname + "1");
}
else
{
dt.Columns.Add(columnname);
}
}
}
return dt;
}
private static List<string> getData(string filename, System.Text.Encoding encoder)
{
System.IO.StreamReader sr = new System.IO.StreamReader(filename, encoder);
List<string> dataList = new List<string>();
string line = sr.ReadLine();
System.Text.StringBuilder lineBuffer = new StringBuilder("");
while (line != null)
{
lineBuffer.Append(line);
if (checkyh(lineBuffer.ToString(),'\"'))
{
dataList.Add(lineBuffer.ToString());
lineBuffer = new StringBuilder("");
}
line = sr.ReadLine();
}
sr.Close();
return dataList;
}
public static bool checkyh(string str,char cp)
{
int i = 0;
foreach (char c in str)
{
if(c=='\"')
{
i++;
}
}
if (i % 2 == 0)
{
return true;
}
else
{
return false;
}
}
}
}