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

C#中如何实现对象与固定长度字符串的序列化/反序列化?

C# 固定长度字符串序列化与反序列化实现方案

针对你的需求,C# 没有现成的通用序列化器完全匹配这种固定长度+空格填充的格式,但可以通过以下两种方案实现,兼顾简单性和复用性:

一、手动实现(适合结构固定的简单类)

对于你的Record类,直接编写序列化和反序列化方法是最直观高效的方式:

序列化方法

public static string SerializeRecord(Record record)
{
    // Identifier 固定4位,空值或长度不足补空格,超过则截断
    var identifier = record.Identifier?.PadRight(4).Substring(0, 4) ?? new string(' ', 4);
    // ProcessAbbreviation 固定8位(对应原需求的第5-12位)
    var processAbbr = record.ProcessAbbreviation?.PadRight(8).Substring(0, 8) ?? new string(' ', 8);
    // Name 固定4位(对应原需求的第13-16位)
    var name = record.Name?.PadRight(4).Substring(0, 4) ?? new string(' ', 4);
    
    return string.Concat(identifier, processAbbr, name);
}

反序列化方法

public static Record DeserializeRecord(string fixedLengthString)
{
    if (fixedLengthString.Length != 16) // 总长度4+8+4=16位
        throw new ArgumentException("输入字符串长度不符合固定格式要求");
    
    return new Record
    {
        Identifier = fixedLengthString.Substring(0, 4).TrimEnd(), // 去除末尾填充的空格
        ProcessAbbreviation = fixedLengthString.Substring(4, 8).TrimEnd(),
        Name = fixedLengthString.Substring(12, 4).TrimEnd()
    };
}

这个方案的优势是性能高、逻辑清晰,适合不需要复用的单一类场景。

二、特性驱动的通用实现(适合多类复用)

如果后续有多个类需要类似的固定长度序列化,可以通过自定义特性+反射实现通用工具类,避免重复代码:

1. 定义固定长度特性

[AttributeUsage(AttributeTargets.Property)]
public class FixedLengthAttribute : Attribute
{
    public int Length { get; }

    public FixedLengthAttribute(int length)
    {
        Length = length;
    }
}

2. 为Record类属性标记特性

public class Record
{
    [FixedLength(4)]
    public string Identifier { get; set; }

    [FixedLength(8)]
    public string ProcessAbbreviation { get; set; }

    [FixedLength(4)]
    public string Name { get; set; }
}

3. 通用序列化反序列化工具

public static class FixedLengthSerializer
{
    public static string Serialize<T>(T obj) where T : new()
    {
        // 按类中属性定义顺序获取标记了特性的属性
        var properties = typeof(T).GetProperties()
            .Where(p => p.GetCustomAttribute<FixedLengthAttribute>() != null)
            .OrderBy(p => p.MetadataToken);

        var result = new StringBuilder();

        foreach (var prop in properties)
        {
            var lengthAttr = prop.GetCustomAttribute<FixedLengthAttribute>();
            var value = prop.GetValue(obj)?.ToString() ?? string.Empty;
            // 填充空格并截断到指定长度
            var fixedValue = value.PadRight(lengthAttr.Length).Substring(0, lengthAttr.Length);
            result.Append(fixedValue);
        }

        return result.ToString();
    }

    public static T Deserialize<T>(string fixedLengthString) where T : new()
    {
        var obj = new T();
        var properties = typeof(T).GetProperties()
            .Where(p => p.GetCustomAttribute<FixedLengthAttribute>() != null)
            .OrderBy(p => p.MetadataToken);

        int currentIndex = 0;

        foreach (var prop in properties)
        {
            var lengthAttr = prop.GetCustomAttribute<FixedLengthAttribute>();
            if (currentIndex + lengthAttr.Length > fixedLengthString.Length)
                throw new ArgumentException("输入字符串长度不足,无法完成反序列化");

            var value = fixedLengthString.Substring(currentIndex, lengthAttr.Length).TrimEnd();
            prop.SetValue(obj, value);
            currentIndex += lengthAttr.Length;
        }

        if (currentIndex != fixedLengthString.Length)
            throw new ArgumentException("输入字符串长度超出预期格式");

        return obj;
    }
}

使用示例

// 序列化
var record = new Record
{
    Identifier = "AAAA",
    ProcessAbbreviation = "BBBB",
    Name = "CCCC"
};
var serializedStr = FixedLengthSerializer.Serialize(record);
// 输出结果:"AAAABBBB    CCCC"

// 反序列化
var deserializedRecord = FixedLengthSerializer.Deserialize<Record>(serializedStr);

这个方案的优势是可复用性强,新增类时只需标记特性即可,缺点是反射会带来轻微的性能开销,对性能要求极高的场景建议用手动实现。

内容的提问来源于stack exchange,提问作者Maik Hasler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:15:29