CSV格式解析困惑:为何常见工具偏离RFC 4180标准?
解析非标准CSV文件的问题与解决
核心问题:CSV规范非强制导致的「野路子」实现
你对RFC 4180的理解完全正确:多字段场景下,正确的CSV表示应为A,"""B""",C;而"A, ""B"", C"确实不符合规范——它将整行当作单个带引号的字段,会被严格遵循RFC的解析器(如CsvHelper)识别为单一字段。
这种看似错误的格式广泛存在,主要有两个原因:
- 规范非强制性:RFC 4180只是CSV格式的推荐标准,并非强制要求。很多工具(尤其是旧版办公软件、自定义导出工具)为简化实现,直接把整行内容用双引号包裹,内部字段用逗号分隔,仅对字段内的双引号做
""转义,完全跳过了字段级的引号包裹逻辑。 - 历史兼容性:部分老旧系统仅支持这种整行带引号的格式,新工具为兼容这些系统,也会默认生成此类非标准CSV。
针对实际场景的解决办法
以你提供的示例行"00AA12345,30/11/2023,30/11/2023,01/12/2023,01/12/2023,""BAS"",1 111 000.27,""NRT"",""Test, ok"","""","""","""","""",""""为例,可通过以下步骤处理:
- 预处理行文本:先去掉每行首尾的双引号(仅去除首尾的一对,不要处理内部的)。处理后该行变为:
00AA12345,30/11/2023,30/11/2023,01/12/2023,01/12/2023,"BAS",1 111 000.27,"NRT","Test, ok","","","","","" - 正常解析:此时处理后的文本完全符合RFC 4180规范,CsvHelper可正常识别各个字段,包括带逗号的
Test, ok和空字符串字段。
如果使用CsvHelper,可在读取前添加自定义预处理逻辑,比如在读取每行时先处理首尾引号:
using (var reader = new StreamReader("your-file.csv")) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Context.ReadFieldAsString = field => { // 仅当字段是整行被包裹的情况,去除首尾引号 if (field.StartsWith('"') && field.EndsWith('"')) { return field.Substring(1, field.Length - 2); } return field; }; // 后续正常读取映射即可 }
(注:如果文件中存在部分行是标准格式、部分行是整行带引号的情况,需添加判断逻辑区分)
内容的提问来源于stack exchange,提问作者NicoD
相关产品推荐
相关产品推荐

