
用 File.ReadAllBytes 读取文件再转十六进制字符串
这是最直接的方式:先读取整个文件为字节数组,再逐字节格式化为两位十六进制字符。适合中小文件(
常见错误是用 Encoding.UTF8.GetString 后再调用 GetBytes —— 这会破坏原始二进制内容,完全不可取。
-
File.ReadAllBytes(path)返回byte[],保持原始字节不变 - 用
string.Join("", bytes.Select(b => b.ToString("x2")))转成小写十六进制字符串(如"48656c6c6f") - 若需大写,改用
"X2"格式(如"48656C6C6F") - 不建议对超大文件一次性读入内存,会触发
OutOfMemoryException
大文件用 FileStream + Span<byte></byte> 流式处理
当文件超过几百 MB,必须避免全量加载。用 FileStream 分块读取,配合 Span<byte></byte> 避免重复分配数组,性能更稳。
注意:别用 StreamReader 或任何基于文本的流——它们会尝试解码,彻底毁掉二进制数据。
- 创建
FileStream时指定FileAccess.Read和FileShare.Read - 分配一个固定大小的
byte[] buffer = new byte[8192],或用stackalloc byte[8192](仅限unsafe上下文) - 循环调用
stream.Read(buffer, 0, buffer.Length),直到返回值为 0 - 每块用
Span<byte>.Slice(0, bytesRead).SequenceEqual(...)</byte>不需要,只需对当前块做ToString("x2")拼接
输出带地址偏移和 ASCII 显示的类 Unix Hex Dump
如果目标是模拟 xxd 或 hexdump -C 的可读格式(含偏移、十六进制区、ASCII 区),就不能只拼字符串,得按行组织。
典型坑是 ASCII 区乱码处理:非打印字符(0x00–0x1F、0x7F)应显示为 .,空格和换行等要保留语义。
- 每行通常 16 字节,偏移用 8 位十六进制左对齐(如
"00000000: ") - 十六进制部分每字节两个字符,每 4 字节加空格分隔(
"48656c6c 6f20776f...") - ASCII 区:对每个字节
b,判断char.IsControl((char)b) || b > 127,是则填'.',否则转(char)b - 最后一行可能不满 16 字节,ASCII 区右侧补空格对齐
注意编码与 BOM 对结果的影响
Hex dump 是对原始字节的忠实呈现,跟文本编码无关。但如果你误用 File.ReadAllText 再转字节,就会引入编码层干扰——比如 UTF-8 BOM(0xEF,0xBB,0xBF)会被自动剥离或错误解释。
哪怕文件本身是纯文本,只要需求是“Hex Dump”,就必须绕过所有编码逻辑,直触字节流。
- 绝对不要用
File.ReadAllText、StreamReader、Encoding.Default - 确认路径存在且有读取权限,否则
File.ReadAllBytes抛FileNotFoundException或UnauthorizedAccessException - Linux/macOS 路径区分大小写,
C:\test.txt和c:\test.txt在 Windows 下等价,但代码里保持一致更安全










