ZetCode

C# BinaryWriter

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 C# 中使用 BinaryWriter 类将二进制数据写入文件。BinaryWriter 提供了将原始数据类型写入流的方法。

BinaryWriter 类将原始数据类型作为特定编码的二进制值写入。 它与 BinaryReader 类一起工作,后者读取二进制数据。

BinaryWriter 对于创建紧凑的二进制文件以有效地存储数据非常有用。 它处理诸如 int、float、double 和字符串之类的数据类型,并具有指定的编码。

基本 BinaryWriter 示例

此示例演示了将原始数据类型写入二进制文件。 我们创建一个新文件并写入几个不同类型的值。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        using (var writer = new BinaryWriter(File.Open("data.bin", FileMode.Create)))
        {
            writer.Write(42);              // Integer
            writer.Write(3.14159);        // Double
            writer.Write(true);           // Boolean
            writer.Write("Hello World");  // String
        }

        Console.WriteLine("Binary data written successfully");
    }
}

该程序创建一个二进制文件并写入四种不同的原始类型。 BinaryWriter 为每种数据类型提供了重载的 Write 方法。 该示例将一个整数、一个双精度浮点数、一个布尔值和一个字符串写入文件。

每个 Write 方法将该值转换为字节序列并将它们写入流。 默认情况下,字符串使用 UTF-8 编码写入,并带有长度前缀。 这使得文件紧凑且存储效率高。

将数组写入二进制文件

BinaryWriter 可以写入原始类型的数组。 此示例展示了如何将整数数组写入二进制文件。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        int[] numbers = { 10, 20, 30, 40, 50 };
        
        using (var writer = new BinaryWriter(File.Open("array.bin", FileMode.Create)))
        {
            writer.Write(numbers.Length);  // Write array length first
            
            foreach (int num in numbers)
            {
                writer.Write(num);        // Write each element
            }
        }

        Console.WriteLine("Array written to binary file");
    }
}

首先写入数组的长度,然后写入每个元素。 这允许在读取时进行正确的重构。 该示例将数组的长度作为整数写入,然后迭代数组并写入每个元素。

此模式在使用二进制文件中的数组时很常见。 读取器将首先读取长度,然后知道要读取多少元素。 这种方法适用于任何原始类型数组。

写入混合数据类型

二进制文件通常包含混合的数据类型。 此示例演示了如何写入具有不同数据结构的二进制文件。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        using (var writer = new BinaryWriter(File.Open("product.bin", FileMode.Create)))
        {
            writer.Write("Laptop");       // String
            writer.Write(1001);           // Integer ID
            writer.Write(999.99m);       // Decimal price
            writer.Write(DateTime.Now.Ticks); // DateTime as ticks
        }

        Console.WriteLine("Mixed data written to binary file");
    }
}

该示例写入一个包含字符串、整数、十进制和 DateTime 值的 product 记录。 每个 Write 方法处理适当的二进制转换。 字符串使用长度前缀写入,数字以二进制形式写入。

DateTime 存储为 ticks(长整数)以进行精确重构。 读取时,读取顺序必须与写入顺序完全匹配,才能正确解释二进制数据。

指定字符串编码

BinaryWriter 支持不同的字符串编码。 此示例展示了如何在写入字符串时指定编码。

Program.cs
using System;
using System.IO;
using System.Text;

class Program
{
    static void Main()
    {
        using (var writer = new BinaryWriter(
            File.Open("encoded.bin", FileMode.Create), Encoding.Unicode))
        {
            writer.Write("Unicode text");  // Written as Unicode
            
            // Write UTF-8 string manually
            byte[] utf8Bytes = Encoding.UTF8.GetBytes("UTF-8 text");
            writer.Write(utf8Bytes.Length);
            writer.Write(utf8Bytes);
        }

        Console.WriteLine("Strings written with different encodings");
    }
}

BinaryWriter 构造函数接受一个 Encoding 参数。 默认情况下,它使用 UTF-8。 此示例显示了 Unicode 编码和手动 UTF-8 写入。

为了完全控制,您可以使用 Encoding 类自己将字符串转换为字节。 当您需要在同一文件中混合编码或使用 BinaryWriter 不直接支持的编码时,这很有用。

写入 MemoryStream

BinaryWriter 不仅限于文件 - 它可以写入任何流。 此示例使用 MemoryStream 将二进制数据写入内存。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        using (var stream = new MemoryStream())
        using (var writer = new BinaryWriter(stream))
        {
            writer.Write(1.61803398875);  // Golden ratio
            writer.Write("Fibonacci");
            writer.Write(new byte[] { 0, 1, 1, 2, 3, 5, 8 });

            // Get the written data
            byte[] data = stream.ToArray();
            Console.WriteLine($"Wrote {data.Length} bytes to memory");
        }
    }
}

MemoryStream 提供内存中的二进制数据存储。 BinaryWriter 将其视为任何其他流目标。 该示例将几个值写入内存。

这种方法对于网络协议或序列化非常有用,在这些情况下,您需要在内存中而不是文件中存储二进制数据。 ToArray 方法将写入的字节作为字节数组检索。

定位和在特定位置写入

BinaryWriter 适用于可查找的流。 此示例演示了如何定位到某个位置并写入数据。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        using (var stream = new FileStream("seek.bin", FileMode.Create))
        using (var writer = new BinaryWriter(stream))
        {
            // Write initial data
            writer.Write(100);
            writer.Write(200);
            
            // Save position of third value
            long thirdValuePos = stream.Position;
            writer.Write(0);  // Placeholder
            
            writer.Write(400);
            writer.Write(500);

            // Go back and write the third value
            stream.Seek(thirdValuePos, SeekOrigin.Begin);
            writer.Write(300);
        }

        Console.WriteLine("File with seek operations written");
    }
}

该示例写入一些值,保存一个位置,写入更多数据,然后返回以更新占位符。 这演示了随机访问写入。

BaseStream 属性提供对底层流的访问以进行查找。 这种技术对于需要标头或需要在写入其他数据后更新值的文件格式非常有用。

将结构体作为二进制数据写入

这个高级示例演示了如何使用内存封送将 C# 结构体作为二进制数据写入。

Program.cs
using System;
using System.IO;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Point3D
{
    public float X;
    public float Y;
    public float Z;
    public int Color;
}

class Program
{
    static unsafe void Main()
    {
        Point3D point = new Point3D { X = 1.0f, Y = 2.0f, Z = 3.0f, Color = 0xFF0000 };
        
        using (var writer = new BinaryWriter(File.Open("point.bin", FileMode.Create)))
        {
            byte[] buffer = new byte[Marshal.SizeOf(typeof(Point3D))];
            
            fixed (byte* ptr = buffer)
            {
                Marshal.StructureToPtr(point, (IntPtr)ptr, false);
                writer.Write(buffer);
            }
        }

        Console.WriteLine("3D point struct written to binary file");
    }
}

StructLayout 属性确保正确的二进制对齐。 封送将结构化数据转换为原始字节。 需要不安全编译。

这种技术非常强大,可以编写与特定内存布局匹配的复杂二进制格式。 它通常用于图形编程和互操作性场景。

来源

BinaryWriter 类文档

本教程介绍了如何在 C# 中使用 BinaryWriter 写入二进制数据,包括原始类型、数组、字符串和结构化数据。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程