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

如何使用FileStream向文本文件的指定位置写入内容?

问题描述

我需要写入符合以下结构的文本文件:
请输入图片描述
目前我尝试使用Seek()和Write()方法实现该需求,但每次写入新数据时原有内容都会被覆盖,最终文件中仅保留一行内容。
请输入图片描述
我使用的代码如下:

private async void CreacionArchivoBCD(ArchivoPerfil contenidoPerfil, string nombreFinalBCD, bool checkPrevia)
{
    var result = await ensayoDataProvider.ObtenerUexCapturador(checkPrevia, contenidoPerfil, codensSeleccionado.Id);
    var cant = System.Text.Encoding.UTF8.GetBytes(Convert.ToString(result.Count()));


    ////TextWriter archivoExportar = new StreamWriter(nombreFinalBCD);
    ////archivoExportar.Close();

    var file = new FileStream(nombreFinalBCD, FileMode.OpenOrCreate, FileAccess.Write);
    file.Seek(1, SeekOrigin.Begin);
    file.Write(cant, 0, cant.Length);
    byte[] newline = Encoding.ASCII.GetBytes(Environment.NewLine);
    file.Write(newline, 0, newline.Length);

    int nroMedAux = 0;
    long rutaAux = 0;
    var cont = 0;
    var bandera = 0;
    //var posicion = 0;
    foreach (var item in result)
    {
        var primerByte = System.Text.Encoding.UTF8.GetBytes("00");
        file.Seek(0, SeekOrigin.Begin);
        file.Write(primerByte, 0, primerByte.Length);

        if (bandera == 0)
        {
            nroMedAux = item.IdMed;
            rutaAux = item.Ruta;
            bandera = 1;
        }

        var tipo = item.GetType();

        if (nroMedAux != item.IdMed || rutaAux != item.Ruta)
        {
            nroMedAux = item.IdMed;
            rutaAux = item.Ruta;
            file.Write(newline, 0, newline.Length);
        }

        foreach (var pi in tipo.GetProperties())
        {
            var propName = pi.Name;
            var propValue = pi.GetValue(item, null)?.ToString();
            var propValueAux = propName == "Campo" ? item.GetType().GetProperty("Valor").GetValue(item, null) : propValue;

            if (propName == "IdMed" || propName == "Valor")
            {
                continue;
            }

            //TODO: buscar posicion y ancho por nombre campo
            var posicion = BuscarPosicion(propName, propValue, contenidoPerfil);
            //var ancho = BuscarAncho(propName, contenidoPerfil);

            Debug.WriteLine(propName);
            Debug.WriteLine(propValueAux);
            Debug.WriteLine(posicion);

            if (posicion == -1)
            {
                continue;
            }

            var lacadena = propValue;
            var lacadenAux = propName == "Campo" ? propValueAux : propValue;
            var cadena = System.Text.Encoding.UTF8.GetBytes(lacadenAux.ToString());
            file.Seek(posicion, SeekOrigin.Begin);
            file.Write(cadena, 0, cadena.Length);
        }
    }

    file.Close();

}
问题原因&修复方案

核心问题

内容覆盖的问题主要来自两处错误用法:

  1. 循环内每次都执行file.Seek(0, SeekOrigin.Begin),强制把写入位置跳转到文件开头,后续写入自然会覆盖开头的原有内容
  2. 所有字段写入都直接用Seek(posicion, SeekOrigin.Begin),如果posicion是字段在当前行的相对偏移,直接从全局文件开头计算位置,就会反复覆盖前面行的内容,最终只会保留最后一行的写入结果

修复要点

  • 移除循环开头的Seek(0, SeekOrigin.Begin)调用,避免每次循环都覆盖文件头部内容
  • 按行管理偏移:每次新增行后记录当前行的起始偏移,该行内所有字段的写入位置都按当前行起始偏移+字段相对偏移计算,不要直接使用全局文件开头的位置
  • 用using包裹FileStream,自动处理资源释放,避免异常场景下文件流泄漏
  • 如果第一行需要写入总条数,建议优先计算好总条数再写入,避免后续行写入覆盖头部统计值

修复后参考代码

private async void CreacionArchivoBCD(ArchivoPerfil contenidoPerfil, string nombreFinalBCD, bool checkPrevia)
{
    var result = await ensayoDataProvider.ObtenerUexCapturador(checkPrevia, contenidoPerfil, codensSeleccionado.Id);
    // 先获取总条数,后续统一写入
    string countStr = result.Count().ToString();
    byte[] newline = Encoding.UTF8.GetBytes(Environment.NewLine);

    // using自动释放流,不需要手动调用Close
    using var file = new FileStream(nombreFinalBCD, FileMode.Create, FileAccess.Write);
    // 写入第一行总条数
    byte[] countBytes = Encoding.UTF8.GetBytes(countStr);
    file.Write(countBytes, 0, countBytes.Length);
    file.Write(newline, 0, newline.Length);
    // 记录当前行的起始偏移
    long currentLineStart = file.Position;

    int nroMedAux = 0;
    long rutaAux = 0;
    var bandera = 0;

    foreach (var item in result)
    {
        // 首行写入00标识,不要跳回全局文件开头
        if (bandera == 0)
        {
            var primerByte = Encoding.UTF8.GetBytes("00");
            file.Seek(currentLineStart, SeekOrigin.Begin);
            file.Write(primerByte, 0, primerByte.Length);
            nroMedAux = item.IdMed;
            rutaAux = item.Ruta;
            bandera = 1;
        }

        var tipo = item.GetType();
        if (nroMedAux != item.IdMed || rutaAux != item.Ruta)
        {
            nroMedAux = item.IdMed;
            rutaAux = item.Ruta;
            // 写入换行
            file.Write(newline, 0, newline.Length);
            // 更新新行的起始偏移
            currentLineStart = file.Position;
        }

        foreach (var pi in tipo.GetProperties())
        {
            var propName = pi.Name;
            var propValue = pi.GetValue(item, null)?.ToString();
            var propValueAux = propName == "Campo" ? item.GetType().GetProperty("Valor").GetValue(item, null) : propValue;

            if (propName == "IdMed" || propName == "Valor")
            {
                continue;
            }

            var posicion = BuscarPosicion(propName, propValue, contenidoPerfil);
            if (posicion == -1)
            {
                continue;
            }

            var lacadenAux = propName == "Campo" ? propValueAux : propValue;
            var cadena = Encoding.UTF8.GetBytes(lacadenAux.ToString());
            // 写入位置 = 当前行开头 + 字段相对偏移
            file.Seek(currentLineStart + posicion, SeekOrigin.Begin);
            file.Write(cadena, 0, cadena.Length);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 06:45:04