如何用CsvHelper写入未转义带引号值?配置疑问求助
CsvHelper如何写入未转义的带引号值?
问题场景
原始输入CSV内容:
Jake|"B" Street
通过以下读取配置,已成功读取到未转义的字段值"B" Street:
var readerConfig = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", TrimOptions = TrimOptions.Trim, IgnoreBlankLines = true, Mode = CsvMode.NoEscape };
但写入CSV时遇到两难情况:
- 不设置
CsvMode.NoEscape,仅开启ShouldQuote = args => true:输出为"""B"" Street"(字段内双引号被转义) - 设置
CsvMode.NoEscape且开启ShouldQuote = args => true:输出不带引号,仅为"B" Street
当前使用的写入配置:
writerConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) { ShouldQuote = args => true, Mode = CsvMode.NoEscape };
解决方案
要实现带引号包裹且字段内双引号不转义的目标,核心是手动控制引号的添加,结合CsvMode.NoEscape禁用转义逻辑:
方法1:手动处理字段输出
关闭自动引号功能,在写入时为目标字段手动添加引号:
var writerConfig = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", Mode = CsvMode.NoEscape, ShouldQuote = args => false // 禁用自动引号处理 }; using (var writer = new CsvWriter(yourTextWriter, writerConfig)) { foreach (var record in yourRecords) { writer.WriteField(record.Name); // 手动给需要带引号的字段添加双引号 writer.WriteField($"\"{record.Street}\""); writer.NextRecord(); } }
方法2:自定义类型转换器(更优雅)
针对需要特殊处理的字段,自定义转换器来添加引号,同时保持配置简洁:
- 定义转换器:
public class UnescapedQuoteConverter : StringConverter { public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData) { var strValue = value as string; return strValue != null ? $"\"{strValue}\"" : base.ConvertToString(value, row, memberMapData); } }
- 配置字段映射:
public sealed class RecordMap : ClassMap<YourRecordType> { public RecordMap() { Map(m => m.Name); // 为目标字段应用自定义转换器 Map(m => m.Street).TypeConverter<UnescapedQuoteConverter>(); } }
- 写入配置及执行:
var writerConfig = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", Mode = CsvMode.NoEscape, ShouldQuote = args => false }; using (var writer = new CsvWriter(yourTextWriter, writerConfig)) { writer.Context.RegisterClassMap<RecordMap>(); writer.WriteRecords(yourRecords); }
核心逻辑说明
CsvMode.NoEscape会完全禁用CsvHelper的转义处理,但同时也会关闭自动引号包裹的逻辑。因此不能依赖ShouldQuote来自动添加引号,必须通过手动拼接或自定义转换器的方式,主动为字段添加外层引号,从而得到Jake|"B" Street的预期输出。
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

