2011-06-07 179 views
4

我需要解析一个utf8编码的csv。转换后,我刚看到问题出现在BOM()字符处。我无法使用utf8编码创建避免BOM的csv,因为即使它是utf8编码,也需要解析它。如何从UTF 8编码的csv中删除BOM(?)字符?

中的任何一个,请告诉我,我怎样才能从CSV使用C#.NET删除BOM()字符..

更新:我已经加入我的代码读取因为即时通讯的CSV头在文件的开头获取BOM。

string CSVConnectionString = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" + ConfigurationSettings.AppSettings["CSVFolder"].ToString() + ";Extensions=asc,csv,tab,txt;Persist Security Info=False;"; 

     using (OdbcConnection Connection = new OdbcConnection(CSVConnectionString)) 
     { 
      List<string> CSVHeaders = new List<string>(); 

      string SelectQuery = string.Format(@"SELECT TOP 1 * FROM [{0}]", CSVFileName); 

      OdbcCommand Command = new OdbcCommand(SelectQuery, Connection); 

      Connection.Open(); 

      OdbcDataReader Reader = Command.ExecuteReader(System.Data.CommandBehavior.CloseConnection); 

      int ColumnCount = Reader.FieldCount; 

      for (int column = 0; column < ColumnCount; column++) 
      { 
       CSVHeaders.Add(Reader.GetName(column)); 
      } 

      return CSVHeaders; 
     } 
+1

您不需要删除BOM,只需要正确读取文件。你的代码是什么样的? – 2011-06-07 05:38:30

+0

@ Jeff,我编辑了我的问题,代码为 – Harun 2011-06-07 05:57:22

+0

我无法正确读取文件,因为它是作为上载到Solr的一部分读取的。如果您真的想在您的代码片段中使用csvtext驱动程序,则可以使用FileReader和FileWriter组合来创建一个Path,我需要发送没有BOM的文件,如Simon的新UTF8Encoding(false) – 2012-09-06 15:12:01

回答

2

这里是做了这样的功能:

public static void SaveAsUTF8WithoutByteOrderMark(string fileName) 
    { 
     SaveAsUTF8WithoutByteOrderMark(fileName, null); 
    } 

    public static void SaveAsUTF8WithoutByteOrderMark(string fileName, Encoding encoding) 
    { 
     if (fileName == null) 
      throw new ArgumentNullException("fileName"); 

     if (encoding == null) 
     { 
      encoding = Encoding.Default; 
     } 

     File.WriteAllText(fileName, File.ReadAllText(fileName, encoding), new UTF8Encoding(false)); 
    } 
+0

如果文件没有编码或用其他编码进行编码,这是否合适?我的意思是,我应该只用于utf8编码的文件。 – Harun 2011-06-07 06:55:22

+0

我不会推荐这种方式来处理大文件。 – svick 2011-06-07 06:57:59

+0

@哈伦 - 不,这个函数只适用于UTF8输入文件,或者输入文件只包含ASCII字符。 – 2011-06-07 07:02:54

4

实际上,C#可以读取包含BOM的UTF-8编码文件。这是您使用的破损的CSV文本驱动程序,实际上是导致问题的原因。我建议使用this answer的其他CSV阅读解决方案之一。

+0

。 GetTempFilename()不含BOM的文件副本 – eFloh 2011-06-07 06:54:32

+0

这很好用...感谢您的回答。如果直到现在我还没有完成,我肯定会使用它。我无法在使用新的外部DLL后重新运行我的完整测试用例。 – Harun 2011-06-07 07:38:18

+0

@Harun:不确定“新的外部DLL”是什么意思......你的意思是你不能为这个项目添加新的引用?在这种情况下,也许你可以使用[Microsoft.VisualBasic.FileIO.TextFieldParser](http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx),因为它是.NET Framework。 – 2011-06-07 15:36:10

1

而是改变马(使用其他.csv驱动程序)或通过拉自己的车(更改编码)有助于给定的马,你应该告诉马(标准的ODBC文本驱动程序),它需要通过增加一个schema.ini文件就知道做工作:

[withbomgood.txt] 
Format=TabDelimited 
ColNameHeader=True 
CharacterSet=65001 
Col1=FrsColümn CHAR 

定义withbomgood.txt的格式:

FrsColümn 
whätever 

这是withbombad.txt的精确副本;这两个文件有一个BOM:

FrsColümn 
whätever 

如果你现在打电话稍微修改副本

static void Harun00(string CSVFileName) 
{ 
    string CSVFilePath = @"E:\trials\SoTrials\answers\6260911\data"; 
    string CSVConnectionString = 
     "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" + 
     CSVFilePath + 
     ";Extensions=asc,csv,tab,txt;Persist Security Info=False;"; 

    using (OdbcConnection Connection = new OdbcConnection(CSVConnectionString)) 
    { 
     List<string> CSVHeaders = new List<string>(); 

     string SelectQuery = string.Format(@"SELECT TOP 1 * FROM [{0}]", CSVFileName); 

     OdbcCommand Command = new OdbcCommand(SelectQuery, Connection); 

     Connection.Open(); 

     OdbcDataReader Reader = Command.ExecuteReader(System.Data.CommandBehavior.CloseConnection); 

     int ColumnCount = Reader.FieldCount; 

     for (int column = 0; column < ColumnCount; column++) 
     { 
      CSVHeaders.Add(Reader.GetName(column)); 
     } 

     Console.WriteLine(CSVHeaders[0]); 
    } 
} 
代码的

两次:

static void Main(string[] args) 
{ 
    Harun00("withbombad.txt"); 
    Harun00("withbomgood.txt"); 
} 

你:

FrsColümn 
FrsColümn 
Press any key to continue . . . 

证明司机会读取UT F8与BOM文件正确,如果遵循以下规则,则不需要任何其他ADO:在schema.ini文件中定义您的csv表。

+0

虽然神秘,但这个答案实际上对我有效。为了澄清,我使用Col#= {ColumnName} {Type}格式指定了所有列,不同之处在于我为Type指定了第一列,即使在我的情况下它确实是一个Long。参考[http://msdn.microsoft.com/en-us/library/windows/desktop/ms709353(v=vs.85).aspx]MSDN。 – Vic 2012-10-23 23:29:35