C# StreamWriter 写入字节数组两种方案

C# StreamWriter 写入字节数组两种方案

先分清核心概念:
StreamWriter字符写入器,只负责字符串/字符;它本身没有直接写入 byte[] 的方法
字节数组属于二进制数据,有两种实现思路:

  1. 先把 byte[] 转字符串,再用 StreamWriter 写入(字节当文本)
  2. 拿到底层 FileStream,直接 Write 字节数组(推荐,原生写二进制)

一、方式1:byte[] → 字符串 → StreamWriter写入(字节作为文本保存)

适用场景:字节是文本编码后的内容,需要以文本形式存到txt。
原理:用对应编码把 byte[] 解码成 string,再 Write/WriteLine。

using System;
using System.IO;
using System.Text;

class Program
{
    static void Main()
    {
        // 原始字节数组(UTF8编码的中文)
        byte[] buffer = Encoding.UTF8.GetBytes("测试字节数组文本");

        string path = "byteToStr.txt";
        Encoding utf8NoBom = new UTF8Encoding(false);

        using (StreamWriter sw = new StreamWriter(path, false, utf8NoBom))
        {
            // 字节数组解码为字符串
            string text = utf8NoBom.GetString(buffer);
            sw.WriteLine(text);
        }
    }
}

二、方式2:获取底层流,直接写入byte[](真正写二进制字节,推荐)

StreamWriter.BaseStream 获取内部的 FileStream,FileStream 原生支持 Write(byte[], offset, count),可以直接写入字节数组,不走字符转换。

using System;
using System.IO;
using System.Text;

static void WriteBytesByStreamWriter()
{
    string path = "writeBytes.txt";
    byte[] data = { 0x31, 0x32, 0x33, 0xE4, 0xB8, 0xAD }; // "123中" 的UTF8字节

    using (StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8))
    {
        // 获取底层文件流
        Stream fs = sw.BaseStream;
        // 写入字节数组:数组、起始偏移、写入长度
        fs.Write(data, 0, data.Length);
        
        // 强制刷新缓冲区,确保数据落盘
        fs.Flush();
    }
}

追加模式写入字节

byte[] appendData = Encoding.UTF8.GetBytes("\r\n追加的字节内容");
using (StreamWriter sw = new StreamWriter("writeBytes.txt", true, Encoding.UTF8))
{
    sw.BaseStream.Write(appendData, 0, appendData.Length);
    sw.BaseStream.Flush();
}

三、异步写入字节数组(BaseStream异步)

static async Task WriteBytesAsync()
{
    string path = "asyncBytes.txt";
    byte[] bytes = Encoding.UTF8.GetBytes("异步写入字节");

    using (StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8))
    {
        await sw.BaseStream.WriteAsync(bytes, 0, bytes.Length);
        await sw.BaseStream.FlushAsync();
    }
}

四、重要注意事项

  1. StreamWriter 缓冲冲突
    StreamWriter 自带字符缓冲区,如果你混用 sw.WriteLine()BaseStream.Write(),字符缓冲会优先写入,字节会出现在文字前面/错乱。
    混用前必须先调用 sw.Flush() 清空字符缓冲区:

    using (StreamWriter sw = new StreamWriter("test.txt", false))
    {
        sw.WriteLine("文字内容");
        sw.Flush(); // 先把文字刷进流
        byte[] b = {0x30};
        sw.BaseStream.Write(b,0,b.Length);
    }
    
  2. 不要混淆两种用途

    • 想把字节当成可读文本:用 Encoding.GetString(byte[]) 转字符串再Write
    • 想原样保存二进制字节(文件、加密数据等):直接操作 BaseStream
  3. 编码统一
    通过 BaseStream 写字节时,字节本身是什么编码,文件就是什么编码,不受 StreamWriter 构造函数编码参数影响;
    只有调用 sw.Write(string) 时,才会使用构造传入的编码转字节。

最简封装方法

/// <summary>通过StreamWriter底层流写入字节数组</summary>
static void WriteBytes(StreamWriter sw, byte[] buffer)
{
    if (buffer == null || buffer.Length == 0) return;
    sw.BaseStream.Write(buffer, 0, buffer.Length);
    sw.BaseStream.Flush();
}

调用示例:

byte[] buf = Encoding.UTF8.GetBytes("封装测试");
using var sw = new StreamWriter("demo.txt", false, new UTF8Encoding(false));
WriteBytes(sw, buf);
posted @ 2026-06-19 20:50  人生就是修炼  阅读(4)  评论(0)    收藏  举报