HOWTO · Csharp
在 C# 中将 Int 转换为字节
在这篇文章中,我们将介绍几种在 C# 中将 Int 转换为 Byte 的不同技术。
本页内容
在 C# 中,合适的转换方式取决于你要存储什么。byte 可存放一个介于 0 到 255 之间的无符号值。byte[] 则存放用于表示较大值的字节。若结果应为单个字节,请使用 Convert.ToByte;若需要 int 的二进制表示,请使用 BitConverter.GetBytes 或流。对于文件或网络格式,还应明确指定所需的字节序。
在 byte 和 byte[] 之间选择
int 是有符号的 32 位数,而 byte 是一个无符号的 8 位数。因此,只有当 int 的值介于 0 到 255 之间时,才能将其转换为 byte。相比之下,byte[] 可以保留 int 的全部四个字节;字节排列顺序决定了其他系统如何还原该数值。
对于确定能放入单个字节的值(例如较小的计数或通道值),请选择标量转换。对于序列化、二进制协议或要求字节的 API,请选择数组。将数字转换为十进制文本再编码是另一种操作:它存储的是 1、2、3 这样的字符,而不是整数 123 的二进制表示。
使用 byte 和 Convert.ToByte 转换值
Convert.ToByte 返回单个标量 byte。字符串重载会解析十进制数字文本,数值重载则转换受支持的数值类型。对于整数变量,转换前应确认其值介于 0 到 255 之间。未经检查的强制转换可能会丢弃高位,而不会报告溢出。
运行此示例:
本节中的代码以及显示的标签或输出仍为英文。
using System;
class Program
{
static void Main()
{
string text = "42";
byte fromText = Convert.ToByte(text);
byte fromNumber = Convert.ToByte(90);
Console.WriteLine($"{fromText}, {fromNumber}");
}
}
42, 90
字符串输入为 null 时会转换为 0。不是数字的文本会导致 FormatException,而解析后超出 0 到 255 范围的值会导致 OverflowException。
下一个示例会处理这两种失败情况,并打印捕获到的异常类型,以便区分它们。FormatException 来自非数字文本;OverflowException 则来自解析后大于 255 的值。示例输出中的异常名称保持英文。
运行此失败处理示例:
using System;
class Program
{
static void Main()
{
string[] inputs = { "twelve", "300" };
foreach (string input in inputs)
{
try
{
byte value = Convert.ToByte(input);
Console.WriteLine($"{input} -> {value}");
}
catch (FormatException)
{
Console.WriteLine($"{input} -> FormatException");
}
catch (OverflowException)
{
Console.WriteLine($"{input} -> OverflowException");
}
}
}
}
字符串与基数重载 Convert.ToByte(value, fromBase) 同样返回单个字节。它支持基数 2、8、10 和 16;并不支持从 2 到 36 的所有基数。例如,Convert.ToByte("FF", 16) 会解析十六进制值。包含无效数字字符或超出 byte 范围的值会导致转换错误;基数不在支持范围内则会导致 ArgumentException。不要将此重载描述为把整数转换成字节数组。
使用 BitConverter.GetBytes 将 int 转换为 byte[]
BitConverter.GetBytes(int) 会返回包含该整数二进制表示的四个字节。字节顺序取决于当前机器,可通过 BitConverter.IsLittleEndian 查看。下面的完整示例会以十进制数字打印这些字节,并指出机器使用的本机字节序。示例中的 Little-endian 和 Big-endian 标签保持英文。
本节中的代码以及显示的标签或输出仍为英文。
using System;
class Program
{
static void Main()
{
int value = 123456789;
byte[] bytes = BitConverter.GetBytes(value);
Console.WriteLine(string.Join(" ", bytes));
Console.WriteLine(BitConverter.IsLittleEndian ? "Little-endian" : "Big-endian");
}
}
当接收端使用相同的字节序约定时,这种方法很方便。如果要将字节存储或发送到其他系统,应先约定格式,不要假设两台机器使用相同的字节顺序。
使用 BinaryWriter 和 MemoryStream 将 int 写入 byte[]
如果代码已经在向流写入一系列值,可以用 BinaryWriter 写入 int,再通过 MemoryStream.ToArray() 获取累计的字节。BinaryWriter 会按小端顺序写入其原始数值类型。读取流内容前应先释放 writer,确保缓冲工作已完成;释放 writer 也会释放流,但之后仍可调用 ToArray()。
本节中的代码以及显示的标签或输出仍为英文。
using System;
using System.IO;
class Program
{
static void Main()
{
int value = 987654321;
byte[] bytes;
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(value);
}
bytes = stream.ToArray();
}
Console.WriteLine(string.Join(" ", bytes));
}
}
当需要按顺序序列化多个字段时,这种方式很有用。生成的数组包含流的全部内容,而不只是最后写入的整数。如果协议指定了其他字节序,请使用该协议要求的明确顺序。
将 int 转换为 byte[] 时控制字节顺序
端序决定最低有效字节或最高有效字节哪个先出现。BitConverter.GetBytes 使用机器的本机字节序,因此只有在本机字节序与所需格式不同时,才应反转数组副本。下面的示例会为同一个值分别生成小端和大端表示,不受机器本机字节序影响;输出中的 Little-endian 和 Big-endian 标签保持英文。
本节中的代码以及显示的标签或输出仍为英文。
using System;
class Program
{
static void Main()
{
int value = 567890123;
byte[] native = BitConverter.GetBytes(value);
byte[] littleEndian = (byte[])native.Clone();
byte[] bigEndian = (byte[])native.Clone();
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(littleEndian);
}
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bigEndian);
}
Console.WriteLine("Little-endian: " + string.Join(" ", littleEndian));
Console.WriteLine("Big-endian: " + string.Join(" ", bigEndian));
}
}
应在写入或读取字节的边界处指定所需顺序。对于定宽整数表示,反转本地数组是恰当的做法,但这并不能定义完整的序列化格式:格式还必须指定宽度、有无符号,以及多个字段的排列顺序。