You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于SoftCircuit CsvParser处理混合固定/变长格式文件的技术咨询

关于SoftCircuit CsvParser处理混合固定/变长格式文件的技术咨询

我完全理解你的困扰——SoftCircuit CsvParser默认的固定宽度或分隔模式确实没直接支持这种混合场景,而且你尝试的DataConverter没触发也在情理之中:因为在固定宽度解析模式下,库会严格按照FixedWidthField标注的宽度分割字段,没标注的字段它根本不知道该怎么定位,自然不会调用转换器。设超大宽度报错则是因为库会尝试读取指定长度的字符,一旦行的实际长度不够就会抛出越界异常。

不过不用彻底放弃这个库的投资,我们可以结合它的固定字段解析能力,再通过事件扩展来处理变长字段,给你两个可行的方案:

方案一:利用RowRead事件手动处理变长字段

这个方法既保留了库对前两个固定字段的自动解析,又能灵活处理第三个变长字段:

首先调整你的DTO,去掉第三个字段的ColumnMap标注(因为固定宽度模式下它不会生效):

public class MyDto 
{ 
    [FixedWidthField(13)] 
    public string? Column1 { get; set; } 
    [FixedWidthField(5)] 
    public string? Length { get; set; } 
    public string? Description { get; set; } 
}

然后在解析时订阅RowRead事件,拿到原始行字符串后手动提取第三个字段:

var parser = new CsvParser<MyDto>();
parser.RowRead += (sender, e) =>
{
    string rawRow = e.Context.RawRow;
    if (string.IsNullOrEmpty(rawRow)) return;

    // 前两个字段总长度:13(Column1) + 5(Length)= 18
    int descStartIndex = 13 + 5;
    if (int.TryParse(e.Row.Length, out int targetLength))
    {
        // 按Length字段指定的长度提取,避免越界
        int actualLength = Math.Min(targetLength, rawRow.Length - descStartIndex);
        e.Row.Description = rawRow.Substring(descStartIndex, actualLength).Trim();
    }
    else
    {
        // 如果Length解析失败,直接取到行尾
        e.Row.Description = rawRow.Substring(descStartIndex).Trim();
    }
};

// 执行文件解析
var records = parser.ParseFile("your-input-file.txt");

这个方案的好处是不用自己写整个解析逻辑,只补充处理变长字段的部分,完全复用了库对固定字段的解析、类型转换等能力。

方案二:自定义固定宽度字段转换器(备选)

如果你更想通过转换器的方式处理,可以尝试给第三个字段标注FixedWidthField,并指定一个足够大的宽度,同时自定义转换器来截断到实际需要的长度:

public class VariableLengthConverter : IDataConverter
{
    public object? Convert(string? value, Type targetType, object? parameter)
    {
        // 注意:转换器无法直接访问DTO的其他属性,所以这个方案更适合第三个字段直接到行尾的场景
        return value?.Trim();
    }
}

// DTO修改如下
public class MyDto 
{ 
    [FixedWidthField(13)] 
    public string? Column1 { get; set; } 
    [FixedWidthField(5)] 
    public string? Length { get; set; } 
    [FixedWidthField(1000, ConverterType = typeof(VariableLengthConverter))] 
    public string? Description { get; set; } 
}

不过这个方案有个明显的缺点:转换器无法直接获取DTO中Length字段的值,所以如果必须严格按Length指定的长度截取,还是方案一更靠谱。

总的来说,方案一应该是最贴合你需求的——既不用放弃之前对库的投资,又完美解决了混合格式的解析问题。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 07:33:01