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

如何将整数转为固定长度字节数组以减少大文件写入的字符串分配?

优化多GB级固定长度文件写入,减少字符串分配

问题背景

需要写入多GB级别的固定长度文件,当前用StreamWriter配合字符串插值的实现会产生大量字符串分配,影响性能。目标是改用FileStream.Write(byte[])直接写入字节数组,彻底避免不必要的内存开销。

当前实现代码:

using (var streamWriter = new StreamWriter(fileName))
{
    for (int i = 0; i < rowsCount; i++)
    {
        foreach (var cellInfo in cellInfos)
            streamWriter.Write($"{cellInfo.Info1[i],-10}{cellInfo.Info2[i],-10}");

        streamWriter.WriteLine();
    }
}

最终需要生成的固定长度文件示例(每个数字左对齐,不足10位补空格):

114001    2979993   1         2238001   324585    2985606   2980884   2532097   2532097   2980884   1         2985606   1         2985606   1492803   1         2791025   2485160   1492803   1         2106095   2720047   971452    2952105   1         2985606   1         2985606   324585    2985606   1195045   2985606   
365001    2973993   1402746   1442502   223569    2738205   1121779   2744137   2744137   1121779   1990399   995210    1990399   995210    1759696   1944745   1598017   2485161   1703338   1195696   979974    2720052   251107    2975092   1990399   995210    1990399   995210    223569    2738205   1130022   995240    

解决方案

核心逻辑是预分配每行的字节数组,将int直接转换为固定长度的字节段填充到数组中,全程避免字符串分配。

1. 基础实现(少量字符串分配)

先实现一个工具方法,把int转成左对齐、长度为10的字节数组:

private static void IntToFixedLengthBytes(int value, byte[] buffer, int startIndex, Encoding encoding)
{
    string str = value.ToString();
    byte[] strBytes = encoding.GetBytes(str);
    // 复制数字字节到目标数组
    Buffer.BlockCopy(strBytes, 0, buffer, startIndex, strBytes.Length);
    // 剩余位置填充空格(ASCII空格字节值为32)
    int spaceCount = 10 - strBytes.Length;
    for (int i = 0; i < spaceCount; i++)
    {
        buffer[startIndex + strBytes.Length + i] = 32;
    }
}

完整写入代码:

// 预计算每行字节长度:每个cellInfo输出2个10字节字段
int rowByteLength = cellInfos.Count * 2 * 10;
byte[] rowBuffer = new byte[rowByteLength];
byte[] newLineBytes = Encoding.Default.GetBytes(Environment.NewLine);

using (FileStream fs = File.Create(fileName))
{
    for (int i = 0; i < rowsCount; i++)
    {
        int currentIndex = 0;
        foreach (var cellInfo in cellInfos)
        {
            // 写入Info1[i]
            IntToFixedLengthBytes(cellInfo.Info1[i], rowBuffer, currentIndex, Encoding.Default);
            currentIndex += 10;
            // 写入Info2[i]
            IntToFixedLengthBytes(cellInfo.Info2[i], rowBuffer, currentIndex, Encoding.Default);
            currentIndex += 10;
        }
        // 写入整行数据
        fs.Write(rowBuffer, 0, rowByteLength);
        // 写入换行符
        fs.Write(newLineBytes, 0, newLineBytes.Length);
    }
}

2. 极致优化(零字符串分配)

如果要彻底消除字符串分配,直接将int转换为ASCII字节,跳过字符串中间层:

private static void IntToFixedLengthBytesNoString(int value, byte[] buffer, int startIndex)
{
    // 处理负数(无负数场景可省略)
    bool isNegative = value < 0;
    if (isNegative)
        value = -value;

    // 从后往前填充数字的ASCII字节
    int pos = startIndex + 9;
    do
    {
        buffer[pos--] = (byte)('0' + (value % 10));
        value /= 10;
    } while (value > 0 && pos >= startIndex);

    // 写入负号
    if (isNegative && pos >= startIndex)
        buffer[pos--] = (byte)'-';

    // 剩余位置填充空格
    while (pos >= startIndex)
        buffer[pos--] = 32;
}

使用时替换上述IntToFixedLengthBytes即可,适合超大规模数据写入场景。

内容的提问来源于stack exchange,提问作者Rand Random

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:45:42