2011-03-21 99 views
1

我想一个CSV加载到数据表中使用这样的:故障解析的Unicode CSV文件

class CSVReader 
{ 
    public System.Data.DataTable GetDataTable(string strFileName) 
    { 
     System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection 
     (
     "Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + 
     "; Extended Properties = \"Text;HDR=YES;FMT=Delimited\"" 
     ); 
     conn.Open(); 
     string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]"; 
     System.Data.OleDb.OleDbDataAdapter adapter = new System.Data.OleDb.OleDbDataAdapter(strQuery, conn); 
     System.Data.DataSet ds = new System.Data.DataSet("CSV File"); 
     adapter.Fill(ds); 
     return ds.Tables[0]; 
    } 
} 

它正常工作,一个一个CSV,而不是其他。这是不正确加载该文件的片段: enter image description here

它只是加载“T”作为第一个列名,其他一切都是空/空。我试图手动看第一行以

Using (StreamReader x = new StreamReader(fileName) { string firstline x = x.ReadLine(); } 

和等效File.ReadAllLines和参考阵列的“0”条目(文件[0])。

两者都简单地将“T”作为“第一行”返回,超出这个范围的任何内容都是空白的。任何想法为什么它只能看到CSV中的第一个字符而没有其他的东西?

编辑:第一行看起来像这样:

术语(复数),OBJECTID,FILE,PATH,命中计数

第二行看起来像这样:

“(test)”,“172911”,“16369318”,“Item001.E01/Partition 1/NONAME [NTFS]/[unallocated space]/13621367/16369318”,“4”

编辑2: 我切换了lib链接的人(CVSReader),它似乎已经消除了很多痛苦。我试图编码UTF-8的文件用记事本++和它得到更远沿,直到它到达:

LumenWorks.Framework.IO.Csv.MalformedCsvException了未处理 消息=的CSV似乎是接近记录腐败'位置'2601'处的'1373'字段'3。当前原始数据:'32 /System.ServiceModel/06d6eab93282d2b136a377bd50b7c5a9/System.ServiceModel.ni.dll","11“ ”(vc)“,”40656“,”Adobe AIR Application Installer.swf“,”Item001.E01 /分区1/NONAME [NTFS]/[root]/Program Files/Common Files/Adob​​e AIR/Versions/1.0/Adob​​e AIR Application Installer.swf“,”11“ ”(vc)“,”503322“,”䄳䆷䞫䄦䠥”, “Item001.E01 /分区1/NONAME [NTFS]/[根] /WINDOWS/Installer/520ae67.msp/䄳䆷䞫䄦䠥”, “11”

我猜如果我按照原来的方式离开文件,原始编码,它处理得不好/不正确,我不想让用户必须打开文件并保存它作为ASCII/UTF-16,因为它是~90mb。我一直试图谷歌周围,但大多数人说.NET可以处理任何编码。

看来文件输出为UCS-2 LE(我认为它是UTF-16,对吗?)。我“米困惑,为什么CVSReader/StreamReader的服用问题。

诊断,但不能完全解决

当我通过‘字符集= Unicode的’追加到我的OldeDB函数的字符串,它似乎为USC工作-2LE/Unicode编码我宁愿使用CSVReader自定义库,但它似乎使用TextReader(据我所知可以不处理Unicode)。

http://www.codeproject.com/KB/database/CsvReader.aspx

下面的代码将无法正常工作。它不会抛出一个错误,但它似乎停滞了,甚至在自己的线程:

糟糕的代码为USC2/Unicode的:

   using (CsvReader csv = new CsvReader(
          new StreamReader(kwfile, Encoding.Unicode), true)) 
      { 
       csv.MissingFieldAction = MissingFieldAction.ReplaceByEmpty; 
       keywordHits.Load(csv); 
      } 

工作,但不是首选的解决方案:

 public System.Data.DataTable GetDataTable(string strFileName) 
    { 
     System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection 
     (
     "Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + 
     "; Extended Properties = \"Text;characterset=Unicode;HDR=YES;FMT=Delimited\"" 
     ); 
     conn.Open(); 
     string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]"; 
     System.Data.OleDb.OleDbDataAdapter adapter = new System.Data.OleDb.OleDbDataAdapter(strQuery, conn); 
     System.Data.DataSet ds = new System.Data.DataSet("CSV File"); 
     adapter.Fill(ds); 
     return ds.Tables[0]; 
    } 

我已经在CSVReader可选的第三个参数试了一下为好,并没有什么区别。该程序“工作”通过使用CSVReader类加载一个CSV,但必须使用Unicode CSV上的OldeDB。很明显,使用带有Encoding.Unicode参数的StreamReader可以工作,但是我不得不重新发明解析出可能格式错误的条目。有什么想法吗?或者,这是我可以做的最好的,无需重写CSVReader?

+0

你能与虚拟二号线某处发布文件? – 2011-03-21 16:52:40

+1

@jonathan:它是零。期。零upvotes和零“接受”。你在看什么? – 2011-03-21 16:56:34

+0

第二行看起来像这样 “(测试)”, “172911”, “16369318”, “Item001.E01 /分区1/NONAME [NTFS]/[未分配空间] /16369318分之13621367”, “4” – Jai 2011-03-21 16:56:56

回答

4

一种远出手,但也许你的文件是使用UTF-16编码。该文件中的字节会是这样的:

T <NUL> E <NUL> ... 

尝试使用打开文件:

0x54 0x00 0x45 0x00 ... 

使用UTF-8编码(默认为StreamReader)将产生以下字符阅读这些字节二元编辑器。如果编码是意外的,那么在文本编辑器中将其打开并使用适合您的编码进行保存(ASCII或UTF-8是很好的候选)。

+0

这似乎是它。我编辑了我的帖子。感谢让我走上正轨,尽管我仍然有点困惑,但至少我知道发生了什么问题。 – Jai 2011-03-21 18:39:10

0

从一开始就是这个片段?我发现使用OleDb阅读器时,它会将架构基于第一行,这样如果后续行具有更多列,则其他列将被忽略。

我停止使用它因为这个原因。如果你想要轻量级的东西,我在this answer.有一个全功能的CsvReader。

0

当你的文件是UTF-16编码,尝试指定的StreamReader的和/或CVS阅读器代码的编码。 .NET中的默认编码是UTF-8,它将产生Martin Liversage所述的字符。 对于我不知道的CVS类,StreamReader有一个重载的新StreamReader(路径,Encoding.UTF16)。

+0

它看起来像CVS阅读器使用TextReader获取传递给它的StreamReameder。我尝试将一个UTF-16覆盖传递给流读取器,但是从我可以告诉/读取的情况来看,TextWriter仅采用系统的默认编码(UTF-8?)。如果我想使用这个CVSReader,我看不出来了吗? – Jai 2011-03-22 13:35:11

+0

对不起,正如我已经说过的,我不知道您使用的CSVReader。但是TextWriter类也可以使用不同的语句,看一下StreamWriter的子类! – eFloh 2011-03-23 12:31:42