SSIS C#脚本组件解析CDATA中带逗号的CSV数据异常问题
解决SSIS脚本组件中带引号CSV字段的解析问题
问题根源
直接用Split(',')拆分CSV行时,无法识别双引号包裹字段内部的逗号,导致含逗号的字段(比如示例里的Col04)被错误拆分,进而引发数据导入失败。
解决方案
不要手动拆分CSV,改用符合CSV规范的解析方式,以下提供两种可行方案:
方案1:使用TextFieldParser(推荐)
这是.NET官方提供的CSV解析工具,能正确处理带引号的字段、内部逗号等场景。
操作步骤:
- 在SSIS脚本组件的项目中,添加对
Microsoft.VisualBasic程序集的引用; - 替换原有解析代码为以下内容:
using Microsoft.VisualBasic.FileIO; using System.IO; // 保留原有获取XML内容的代码 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(response.Content); var string1 = xmlDoc.SelectSingleNode("response").InnerText; // 将CSV字符串转为可读取的流 using (StringReader sr = new StringReader(string1)) using (TextFieldParser parser = new TextFieldParser(sr)) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); parser.HasFieldsEnclosedInQuotes = true; // 核心:识别双引号包裹的字段 parser.TrimWhiteSpace = false; // 根据需求设置是否去除字段前后空格 // 如需跳过表头,取消下面一行注释 // parser.ReadLine(); while (!parser.EndOfData) { try { string[] fields = parser.ReadFields(); if (fields == null || fields.Length < 16) continue; // 跳过无效行 MMABuffer.AddRow(); MMABuffer.Col01 = string.Join(",", fields); // 原整行内容 MMABuffer.Col02 = fields[0].Trim('"'); // 去除字段前后的引号 MMABuffer.Col03 = fields[1].Trim('"'); MMABuffer.Col04 = fields[2].Trim('"'); MMABuffer.Col05 = fields[3].Trim('"'); MMABuffer.Col06 = fields[4].Trim('"'); MMABuffer.Col07 = fields[5].Trim('"'); MMABuffer.Col08 = fields[6].Trim('"'); MMABuffer.Col09 = fields[7].Trim('"'); MMABuffer.Col10 = fields[8].Trim('"'); MMABuffer.Col11 = fields[9].Trim('"'); MMABuffer.Col12 = fields[10].Trim('"'); MMABuffer.Col13 = fields[11].Trim('"'); MMABuffer.Col14 = fields[12].Trim('"'); MMABuffer.Col15 = fields[13].Trim('"'); MMABuffer.Col16 = fields[14].Trim('"'); MMABuffer.Col17 = fields[15].Trim('"'); } catch (MalformedLineException ex) { // 处理格式错误的行,可按需记录日志 System.Diagnostics.Debug.WriteLine($"无效行: {ex.Message}"); } } }
方案2:使用正则表达式解析
如果不想引用VisualBasic程序集,可以用正则表达式匹配符合CSV规范的字段:
using System.Text.RegularExpressions; // 保留原有获取XML内容的代码 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(response.Content); var string1 = xmlDoc.SelectSingleNode("response").InnerText; string[] splitStart = string1.Split('\n'); // 正则规则:匹配带引号的内容(内部允许逗号),或不带引号的内容直到逗号/行尾 Regex csvRegex = new Regex(@"(""[^""]*""|[^,]+)", RegexOptions.Compiled); foreach (string line in splitStart) { string trimmedLine = line.Trim(); if (string.IsNullOrEmpty(trimmedLine)) continue; // 跳过空行 MatchCollection matches = csvRegex.Matches(trimmedLine); if (matches.Count < 16) continue; string[] fields = matches.Cast<Match>().Select(m => m.Value.Trim('"')).ToArray(); MMABuffer.AddRow(); MMABuffer.Col01 = trimmedLine; MMABuffer.Col02 = fields[0]; MMABuffer.Col03 = fields[1]; MMABuffer.Col04 = fields[2]; MMABuffer.Col05 = fields[3]; MMABuffer.Col06 = fields[4]; MMABuffer.Col07 = fields[5]; MMABuffer.Col08 = fields[6]; MMABuffer.Col09 = fields[7]; MMABuffer.Col10 = fields[8]; MMABuffer.Col11 = fields[9]; MMABuffer.Col12 = fields[10]; MMABuffer.Col13 = fields[11]; MMABuffer.Col14 = fields[12]; MMABuffer.Col15 = fields[13]; MMABuffer.Col16 = fields[14]; MMABuffer.Col17 = fields[15]; }
注意事项
- 方案1的TextFieldParser是官方实现,兼容性和稳定性更好,优先选择;
- 两种方案都会自动处理双引号包裹字段内的逗号,确保字段拆分正确;
- 代码中添加了空行、无效行的判断,避免因数据格式问题引发异常;
- 可根据实际需求调整
TrimWhiteSpace或字段去引号的逻辑。
内容的提问来源于stack exchange,提问作者N B
相关产品推荐
相关产品推荐

