使用OLEDB读取CSV遇双引号时丢失列值的解决办法
解决OLEDB解析含未转义双引号CSV时列丢失的问题
遇到这种第三方CSV里存在未正确转义的双引号导致OLEDB解析出错的情况太常见了,我来给你几个可行的解决思路:
方案1:预处理CSV文件,移除/替换值中的双引号
OLEDB默认把双引号当成字段的文本限定符,单个未成对的双引号会让它误以为字段还没结束,进而跳过后续列。你可以先预处理CSV内容,把值里的双引号替换掉(如果第三方格式混乱,直接全局替换也能快速解决问题):
// 读取原CSV内容 string fullCsvPath = Path.Combine(filePath, fileName); string csvContent = File.ReadAllText(fullCsvPath, Encoding.UTF8); // 将所有双引号替换为单引号(或空字符串,按需选择) csvContent = csvContent.Replace("\"", "'"); // 创建临时文件用于解析 string tempFilePath = Path.Combine(Path.GetTempPath(), $"temp_{Guid.NewGuid()}.csv"); File.WriteAllText(tempFilePath, csvContent, Encoding.UTF8); // 使用临时文件执行原解析逻辑 string connStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Path.GetDirectoryName(tempFilePath) + ";Extended Properties='text;HDR=Yes;IMEX=1;ColNameHeader=True;CharacterSet=65001;FMT=Delimited(,)';"; using (OleDbConnection conn = new OleDbConnection(connStr)) { conn.Open(); table = new DataTable(); var dataAdapter = new OleDbDataAdapter($"select * from [{Path.GetFileName(tempFilePath)}]", conn); dataAdapter.Fill(table); } // 清理临时文件 File.Delete(tempFilePath);
这个方法简单直接,适合处理格式不规范的第三方CSV,缺点是需要额外IO操作,大文件要注意内存占用。
方案2:用schema.ini自定义解析规则
你可以在CSV所在目录下创建schema.ini文件,明确关闭文本限定符的识别,让OLEDB把所有内容当成普通文本:
- 在CSV同目录下创建
schema.ini,内容如下(替换your_file.csv为你的实际文件名):
[your_file.csv] Format=Delimited(,) TextQualifier=None ColNameHeader=True CharacterSet=65001
TextQualifier=None会告诉OLEDB不要把任何字符当作字段包裹符,单个双引号就不会干扰解析流程了。
- 保持你原有的OLEDB代码不变,重新运行即可。
这个方法无需修改CSV内容,但要确保schema.ini和CSV在同一目录,且文件名匹配;如果处理多个CSV,需要在schema.ini里逐个配置。
方案3:替换OLEDB为更灵活的CSV解析库
OLEDB对不规范CSV的兼容性很差,推荐使用专门的CSV解析库(比如CsvHelper,可通过NuGet直接安装),它对异常格式的处理更友好,还不需要依赖ACE驱动:
using CsvHelper; using CsvHelper.Configuration; using System.Globalization; using System.Reflection; // 定义与CSV列对应的实体类(不需要强类型的话也可以用动态解析) public class CsvRecord { public string Col1 { get; set; } public string Col2 { get; set; } public string Col3 { get; set; } public string Col4 { get; set; } } // 解析逻辑 var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = true, Delimiter = ",", // 配置为不识别转义引号,将引号视为普通字符 Mode = CsvMode.NoEscape }; string fullCsvPath = Path.Combine(filePath, fileName); using (var reader = new StreamReader(fullCsvPath, Encoding.UTF8)) using (var csv = new CsvReader(reader, config)) { var records = csv.GetRecords<CsvRecord>(); table = new DataTable(); // 将实体类属性转为DataTable列 foreach (PropertyInfo prop in typeof(CsvRecord).GetProperties()) { table.Columns.Add(prop.Name, prop.PropertyType); } // 将解析结果填充到DataTable foreach (var record in records) { DataRow row = table.NewRow(); foreach (PropertyInfo prop in typeof(CsvRecord).GetProperties()) { row[prop.Name] = prop.GetValue(record) ?? DBNull.Value; } table.Rows.Add(row); } }
这个方案是长期处理第三方CSV最可靠的选择,CsvHelper的配置非常灵活,能应对各种边缘格式问题。
内容的提问来源于stack exchange,提问作者Girish
相关产品推荐
相关产品推荐

