C# StreamWriter 写入字节数组两种方案
先分清核心概念:
StreamWriter 是字符写入器,只负责字符串/字符;它本身没有直接写入 byte[] 的方法。
字节数组属于二进制数据,有两种实现思路:
- 先把 byte[] 转字符串,再用 StreamWriter 写入(字节当文本)
- 拿到底层 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();}
}
四、重要注意事项
-
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); } -
不要混淆两种用途
- 想把字节当成可读文本:用
Encoding.GetString(byte[])转字符串再Write - 想原样保存二进制字节(文件、加密数据等):直接操作
BaseStream
- 想把字节当成可读文本:用
-
编码统一
通过 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);
