SQL Server中Blob转HEX后乱码,如何转换为有效数据?
图像注释Blob数据解析问题
我不确定当前处理项目的方式是否正确。我有一个SQL Server数据库,其中存储着图像的注释数据,该数据以Blob数据类型保存。
我首先尝试使用SELECT语句将Blob转换为文本:
SELECT CONVERT(varchar(max), CONVERT(varbinary(max), blob_column)) FROM table
随后我使用在线工具将其从HEX转换为ASCII,虽然得到了一些数据,但大部分转换后的文本是乱码(下方为Notepad++中的截图)。

能否将这些乱码转换为有用的数据?有没有其他可行的处理方法?
提供的二进制代码
0x08000000050000002B000000030000006100640061000A0100002E0200000000000001000000A047EDE73F000000009DE8E73F010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000FFFF0E00000041006300740069006E00690063002000440061006D0061006700650000FFFFFFFFFFFFFFFF00000000000000009858700BEFB01146B269007757A49399000000000000F03F000000000000F03F010000003F000000010000006E00EC000000320200000000FF0001000000A047EDE73F000000009DE8E73F010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000FFFF0B0000004E00650076007500730028004E00650076006900290000FFFFFFFFFFFFFFFF00000000000000002D2C2B3419D5E846AD84FA0BFC98B7A0000000000000F03F000000000000F03F01000000AC0000000400000062006E0065006F00890100002B010000FF00000001000000A047EDE73F000000009DE8E73F010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000FFFF2200000052002F004F0020004E0065006F0070006C00610073006D0020006F006600200075006E006300650072007400610069006E0020006200650068006100760069006F00720000FFFFFFFFFFFFFFFF00000000000000001BC3C234AA150C42A01F6B2086317E8C000000000000F03F000000000000F03F01000000AC0000000400000062006E0065006F009A0100004F010000FF00000001000000A047EDE73F000000009DE8E73F010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000FFFF2200000052002F004F0020004E0065006F0070006C00610073006D0020006F006600200075006E006300650072007400610069006E0020006200650068006100760069006F00720000FFFFFFFFFFFFFFFF0000000000000000308BB8069D17AF4FB539F319E8BE2B13000000000000F03F000000000000F03F01000000150000000200000061003100160100001E010000FF00FF0001000000A047EDE73F000000009DE8E73F010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000FFFF090000004D0069006C0064002000410063006E00650000FFFFFFFFFFFFFFFF000000000000000031873239F16ACD48A11A5C0C328705AA000000000000F03F000000000000F03F010000000000000000000000000000000000000000000000
解决方法
1. 修正编码转换方式
乱码核心原因是编码不匹配:你当前用varchar(max)转换默认采用Latin1编码,但Blob中的文本是UTF-16(双字节Unicode)格式。改用nvarchar(max)直接转换即可提取有效文本:
SELECT CONVERT(nvarchar(max), CONVERT(varbinary(max), blob_column)) FROM table
比如你提供的二进制中610064006100片段,用nvarchar转换后会得到正确的ada。
2. 解析结构化Blob数据
从二进制内容看,这不是纯文本Blob,而是带元数据的结构化格式:
- 以
FFFF作为数据块分隔标记 - 每个数据块前4字节是文本长度(小端序整数),后续是UTF-16编码的注释文本,剩余部分为其他元数据(如坐标、时间戳)
手动提取有效文本的步骤:
- 按
FFFF拆分二进制串 - 取每个分段的第5-8字节解析为文本长度(比如第一个分段的
0E000000对应14字节) - 提取对应长度的后续字节,用UTF-16编码解码即可得到注释:
- 第一个分段提取后得到
Active Damage - 其他分段依次可得到
Nevus(Nevi)、R/O Neoplasm of uncertain behavior、Mild Acne等有效内容
- 第一个分段提取后得到
3. 批量解析的程序实现
如果有大量这类Blob,建议用代码批量解析:
C#示例
using (var reader = new BinaryReader(new MemoryStream(blobBytes))) { int blockCount = reader.ReadInt32(); for (int i = 0; i < blockCount; i++) { // 跳过固定长度的头信息 reader.ReadBytes(12); int textLength = reader.ReadInt32(); // 读取UTF-16注释文本 string annotation = reader.ReadString(textLength / 2); // 跳过元数据直到FFFF标记 while (reader.ReadUInt16() != 0xFFFF); Console.WriteLine(annotation); } }
Python示例
import struct # 去掉二进制串开头的0x,转成字节数组 blob_bytes = bytes.fromhex(your_hex_string[2:]) offset = 0 # 读取数据块总数 block_count = struct.unpack('<I', blob_bytes[offset:offset+4])[0] offset +=4 for _ in range(block_count): # 跳过12字节头信息 offset +=12 # 读取文本长度 text_len = struct.unpack('<I', blob_bytes[offset:offset+4])[0] offset +=4 # 解码UTF-16文本 annotation = blob_bytes[offset:offset+text_len].decode('utf-16-le') offset += text_len # 跳过到FFFF标记 while struct.unpack('<H', blob_bytes[offset:offset+2])[0] != 0xFFFF: offset +=2 offset +=2 print(annotation)
4. 反向推导存储逻辑
如果能找到写入该Blob的原始程序(大概率是医学图像标注类工具),可以直接匹配其存储规则,使用对应工具或库解析会更高效。
内容的提问来源于stack exchange,提问作者Peter Sun
相关产品推荐
相关产品推荐

