C#二进制与十六进制数据转换实战:游戏数据库解析与性能优化
1. 项目概述与背景如果你曾经接触过《热血江湖》这类老牌网络游戏的私服搭建或者数据维护那你一定对数据库里那些看起来像天书一样的二进制和十六进制数据字段不陌生。这些数据通常用来存储角色的装备、背包物品、技能状态甚至是任务进度。直接看数据库你看到的可能是一串像0x1A2B3C4D或者0x89ABCDEF这样的十六进制字符串或者干脆就是一堆BLOB类型的二进制数据。对于开发者来说理解并操作这些数据是进行角色数据修复、物品发放、活动配置乃至外挂检测的基础。这个项目要解决的就是如何用 C# 这把瑞士军刀精准、高效地完成这些二进制与十六进制数据之间的转换并理解其在《热血江湖》数据库上下文中的具体含义。这不仅仅是简单的Convert.ToString调用。在游戏数据处理的真实场景里你需要考虑字节序是大端还是小端、数据结构的对齐、特定游戏协议的封装以及如何将一串十六进制数字还原成一个有具体属性的装备对象。无论是想自己写个工具查看角色仓库还是开发一个GM管理后台亦或是分析封包数据这套转换技能都是核心中的核心。接下来我会以一个多年后端开发者的视角拆解这里面的门道从基础原理到实战中的坑让你不仅能写出代码更能明白为什么这么写。2. 核心需求与场景解析2.1 为什么游戏数据库偏爱二进制/十六进制首先得明白游戏尤其是早期的 MMORPG对性能和存储空间极为敏感。一个角色身上可能有几十件装备每件装备有类型、等级、强化次数、附加属性、耐久度等十几个字段。如果每个字段都用独立的数据库列INT, VARCHAR来存一次读取操作会产生大量的 I/O并且表结构会变得异常庞大且难以维护。二进制存储方案将所有这些离散的数据“打包”成一个紧凑的字节序列。比如用 1 个字节8位表示装备类型0-255种足够用 2 个字节表示强化等级0-65535再用 4 个字节表示一个属性值。这样一个装备的所有信息可能只用 10 几个字节就存下了作为一个BLOB或VARBINARY字段存入数据库。十六进制则是二进制的人类可读“展示形式”方便在日志、数据库管理工具中查看和调试。所以我们的核心工作流是从数据库读出二进制字段 - 在 C# 中解析为内存对象结构体或类- 进行业务逻辑处理 - 将内存对象序列化回二进制 - 写回数据库。2.2 典型应用场景游戏管理工具开发这是最直接的需求。你需要开发一个工具让运营人员可以查询某个玩家的背包并以可视化的方式展示物品列表。这需要你读取数据库中的二进制背包数据解析成ListItem并绑定到 UI 控件上。同样发放一件新装备就是创建一个Item对象序列化成二进制再通过 UPDATE 语句写入数据库。数据修复与迁移当游戏版本更新装备系统新增了一个“镶嵌宝石”的属性旧数据的二进制结构就需要升级。你需要写一个数据迁移脚本读取旧的二进制数据按照新规则解析并补充默认值再生成新的二进制格式写回。网络封包分析虽然本文聚焦数据库但原理相通。客户端与服务器通信的封包也常是二进制流。通过抓包工具抓到十六进制流后可以用类似的解析方法分析协议用于安全检测或第三方工具开发。日志分析服务器日志中可能会记录关键操作的二进制数据快照如交易前后的物品数据。分析这些日志需要将其转换回可读格式。3. C# 基础转换机制深度剖析在进入游戏特定格式之前必须牢牢掌握 C# 提供的原生转换工具。这些是构建一切复杂解析器的基石。3.1System.Convert类的功与过Convert类提供了最直观的进制转换正如参考文章里提到的// 十进制转十六进制字符串 string hexString Convert.ToString(255, 16); // 结果为 FF // 十六进制字符串转十进制整数 int number Convert.ToInt32(FF, 16); // 结果为 255 // 十进制转二进制字符串 string binaryString Convert.ToString(10, 2); // 结果为 1010注意事项Convert.ToString(int value, int toBase)的toBase参数只能是 2、8、10 或 16。它返回的是字符串不是字节数组。Convert.ToInt32(string value, int fromBase)在解析十六进制时字符串可以不带0x前缀。但如果字符串包含非指定进制的字符如 “FG” 对于十六进制会抛出FormatException。性能考量对于大规模数据的循环转换Convert方法可能不是最快的。但在大多数管理工具场景下其简洁性远胜于微小的性能开销。3.2 字节、字符串与十六进制字符串的三角关系这是游戏数据处理中最频繁的操作。核心是System.Text.Encoding和byte.ToString(“X2”)。1. 字符串 - 字节数组 - 十六进制字符串这个过程模拟了将一件装备的名称如“屠龙刀”存储为二进制数据的过程。string itemName “屠龙刀”; // 使用特定编码如GBK常见于老游戏将字符串转为字节数组 byte[] nameBytes Encoding.GetEncoding(“GBK”).GetBytes(itemName); // 将字节数组转为十六进制字符串每个字节用两位表示 string hexString BitConverter.ToString(nameBytes).Replace(“-“, “”); // 或者使用循环更可控 StringBuilder sb new StringBuilder(); foreach (byte b in nameBytes) { sb.Append(b.ToString(“X2”)); // “X2” 表示两位大写十六进制不足补零 } hexString sb.ToString(); // 例如 “CDE2C1FAB5B6”关键点编码选择至关重要。《热血江湖》这类游戏客户端很可能是用GB2312或GBK编码处理中文。如果误用UTF-8转换出来的十六进制串会完全不同导致数据解析错误。这需要你通过逆向工程或查阅游戏文档来确认。2. 十六进制字符串 - 字节数组 - 字符串这是读取数据后的还原过程。string hexFromDb “CDE2C1FAB5B6”; // 确保字符串长度为偶数并去除可能的分隔符 hexFromDb hexFromDb.Replace(“ “, “”).Replace(“-“, “”); if (hexFromDb.Length % 2 ! 0) { throw new ArgumentException(“十六进制字符串长度无效。”); } byte[] bytes new byte[hexFromDb.Length / 2]; for (int i 0; i bytes.Length; i) { // 每两个字符解析为一个字节 bytes[i] Convert.ToByte(hexFromDb.Substring(i * 2, 2), 16); } // 使用正确的编码还原字符串 string originalName Encoding.GetEncoding(“GBK”).GetString(bytes); // “屠龙刀”避坑指南数据库或日志中的十六进制字符串可能包含空格、0x前缀或-分隔符如BitConverter生成的格式。在解析前必须进行统一的清理。一个健壮的解析函数应该能处理这些情况。3.3BitConverter数值与字节数组的桥梁游戏数据中大量存在整数HP、MP、金币、浮点数坐标、比例等数值类型。BitConverter是处理它们的利器。int playerGold 1000000; // 将 int 转换为字节数组 byte[] goldBytes BitConverter.GetBytes(playerGold); // 假设 goldBytes 在内存中为 [0x40, 0x42, 0x0F, 0x00] (小端序) // 将字节数组转换回 int int recoveredGold BitConverter.ToInt32(goldBytes, 0);这里隐藏着一个巨坑字节序Endianness。BitConverter.GetBytes的结果取决于当前计算机的 CPU 架构通常是 Little-Endian小端序即低位字节在前。然而网络协议或某些游戏的数据结构可能采用 Big-Endian大端序高位字节在前。《热血江湖》的协议或数据存储格式是哪种这必须通过分析已知数据来确定。如何应对字节序问题如果游戏数据是大端序而BitConverter默认是小端序你就不能直接使用它。你需要手动调整字节顺序int bigEndianValue 0x12345678; byte[] littleEndianBytes BitConverter.GetBytes(bigEndianValue); // 在本机是小端序 // 如果需要转换为大端序的字节数组 if (BitConverter.IsLittleEndian) { Array.Reverse(littleEndianBytes); // 反转后即为大端序 } // 从大端序字节数组解析整数 byte[] networkBytes new byte[] { 0x12, 0x34, 0x56, 0x78 }; if (BitConverter.IsLittleEndian) { Array.Reverse(networkBytes); // 反转后再用 BitConverter 解析 } int value BitConverter.ToInt32(networkBytes, 0); // 得到 0x12345678在实战中我通常会封装两个辅助方法ToBigEndianBytes和FromBigEndianBytes并在其中处理字节序判断和反转逻辑使业务代码保持清晰。4. 实战解析《热血江湖》装备数据结构光说不练假把式。我们假设一个极度简化的《热血江湖》装备数据结构它存储在数据库item_bin字段中VARBINARY(50)。4.1 定义数据结构假设一件装备的二进制格式定义如下按顺序排列装备ID(UInt162字节)物品的基础模板ID。当前耐久度(Byte1字节)0-255。强化等级(Byte1字节)0-15。附加攻击力(Int162字节)有符号整数可能是负数。是否已绑定(Boolean1字节)0 未绑定1 已绑定。装备名称(变长字符串)以0x00(NULL) 结尾的 GBK 编码字符串。4.2 实现解析器反序列化我们将使用BinaryReader来简化按顺序读取字节流的过程。BinaryReader默认使用小端序如果游戏数据是大端序我们需要一个自定义的BigEndianBinaryReader或者像之前说的在读取后手动调整。using System.IO; using System.Text; public class GameItem { public ushort ItemId { get; set; } public byte Durability { get; set; } public byte EnhanceLevel { get; set; } public short ExtraAttack { get; set; } public bool IsBound { get; set; } public string ItemName { get; set; } public static GameItem FromBinary(byte[] data) { if (data null || data.Length 6) // 至少包含前6个固定字段 throw new ArgumentException(“无效的装备数据。”); using (MemoryStream ms new MemoryStream(data)) using (BinaryReader reader new BinaryReader(ms, Encoding.GetEncoding(“GBK”))) // 设置字符串编码 { GameItem item new GameItem(); // 读取固定长度字段 item.ItemId reader.ReadUInt16(); item.Durability reader.ReadByte(); item.EnhanceLevel reader.ReadByte(); item.ExtraAttack reader.ReadInt16(); item.IsBound reader.ReadByte() 1; // 读取字节并转为bool // 读取以 NULL 结尾的字符串 Listbyte nameBytes new Listbyte(); byte b; while ((b reader.ReadByte()) ! 0x00 ms.Position ms.Length) { nameBytes.Add(b); } item.ItemName Encoding.GetEncoding(“GBK”).GetString(nameBytes.ToArray()); return item; } } }实操心得BinaryReader非常适合于这种结构规整的二进制解析代码可读性强。关键是要精确知道每个字段的类型和长度。错一个字节后面的解析会全部乱套。这通常需要查阅游戏的数据结构文档或者通过“黑盒”测试用已知数据对比二进制来推断。字符串的处理是难点。定长、变长、带结束符、前面带长度字节……游戏用哪种必须搞清楚。上述例子是 C 风格的空终止字符串。4.3 实现生成器序列化将GameItem对象写回二进制格式。public byte[] ToBinary() { using (MemoryStream ms new MemoryStream()) using (BinaryWriter writer new BinaryWriter(ms, Encoding.GetEncoding(“GBK”))) { writer.Write(ItemId); writer.Write(Durability); writer.Write(EnhanceLevel); writer.Write(ExtraAttack); writer.Write((byte)(IsBound ? 1 : 0)); // 写入字符串并以 NULL 结尾 if (!string.IsNullOrEmpty(ItemName)) { byte[] nameBytes Encoding.GetEncoding(“GBK”).GetBytes(ItemName); writer.Write(nameBytes); } writer.Write((byte)0x00); // 写入字符串结束符 return ms.ToArray(); } }4.4 整合测试假设我们从数据库读到一个十六进制字符串0x27100A0010C2CCF6C1FA0000已去除0x前缀。string hexFromDatabase “27100A0010C2CCF6C1FA0000”; byte[] itemData HexStringToByteArray(hexFromDatabase); // 使用之前实现的转换函数 GameItem item GameItem.FromBinary(itemData); Console.WriteLine($“装备ID: {item.ItemId}”); // 10000 (0x2710) Console.WriteLine($“耐久: {item.Durability}”); // 10 Console.WriteLine($“强化{item.EnhanceLevel}”); // 0 Console.WriteLine($“附加攻击: {item.ExtraAttack}”); // 16 Console.WriteLine($“已绑定: {item.IsBound}”); // True Console.WriteLine($“名称: {item.ItemName}”); // “屠龙刀” // 序列化回去验证是否一致 byte[] serializedData item.ToBinary(); string hexSerialized ByteArrayToHexString(serializedData); bool isConsistent hexSerialized.Equals(hexFromDatabase, StringComparison.OrdinalIgnoreCase);5. 高级话题与性能优化当处理成千上万个角色数据时性能就变得重要了。5.1 使用SpanT和MemoryT减少分配在 .NET Core 及更高版本中Spanbyte和Memorybyte可以在不分配新数组的情况下操作内存极大提升性能。public static GameItem FromBinarySpan(ReadOnlySpanbyte data) { var item new GameItem(); int offset 0; item.ItemId (ushort)((data[offset 1] 8) | data[offset]); // 手动处理字节序示例 offset 2; item.Durability data[offset]; // … 以此类推解析其他字段 … // 解析字符串 int nameEnd data.Slice(offset).IndexOf((byte)0x00); if (nameEnd 0) { item.ItemName Encoding.GetEncoding(“GBK”).GetString(data.Slice(offset, nameEnd)); offset nameEnd 1; // 1 跳过结束符 } return item; }这种方法避免了BinaryReader内部的一些开销和MemoryStream的分配适合在性能关键的循环中使用。5.2 结构体struct与内存布局对于极度追求性能的场景可以考虑使用struct并配合[StructLayout(LayoutKind.Sequential, Pack 1)]特性让结构体的内存布局与二进制格式严格对齐。然后使用System.Runtime.InteropServices.Marshal进行快速的指针拷贝。但这会大大增加代码的复杂性和不安全上下文的使用除非有确切的性能瓶颈否则不建议在常规管理工具中使用。5.3 缓存与编码重用频繁创建Encoding实例如Encoding.GetEncoding(“GBK”)会有开销。应该在静态字段中缓存它。private static readonly Encoding GbkEncoding Encoding.GetEncoding(“GBK”);同样将十六进制字符对预转换成一个查找表可以加速HexStringToByteArray的转换。private static readonly byte[] HexCharToValue new byte[256]; static YourConverterClass() { for (int i 0; i 256; i) { char c (char)i; int value -1; if (c ‘0’ c ‘9’) value c - ‘0’; else if (c ‘A’ c ‘F’) value c - ‘A’ 10; else if (c ‘a’ c ‘f’) value c - ‘a’ 10; HexCharToValue[i] (byte)value; } } // 在转换函数中使用查找表 byte high HexCharToValue[hexString[i]]; byte low HexCharToValue[hexString[i 1]]; bytes[i / 2] (byte)((high 4) | low);6. 常见问题排查与调试技巧在实际操作中你一定会遇到数据对不上的情况。以下是我总结的排查清单数据完全错乱首先检查字节序。这是最常见的问题。尝试将字节数组Array.Reverse后再解析看数据是否变得合理。可以通过一个已知的数值如一个int类型的 1的二进制格式来验证游戏使用的是哪种字节序。检查字段顺序和长度。你的结构体定义是否与游戏数据的实际排列完全一致用十六进制编辑器如 HxD打开一个已知数据的二进制块一个字节一个字节地核对。字符串解析为乱码编码错误。尝试GB2312,GBK,BIG5,UTF-8,Unicode等不同编码。对于《热血江湖》这类老游戏GBK的概率最大。字符串结束符判断错误。是0x00结尾还是前面有一个表示长度的字节如byte或ushort仔细分析二进制数据中字符串部分的规律。数值范围异常有符号与无符号混淆。游戏数据中一个表示“数量”的字段你用了short有符号-32768~32767解析但游戏实际用的是ushort无符号0~65535。当数值超过 32767 时你的解析结果就会变成负数。位字段Bit Field。有时一个字节的 8 个位分别代表 8 个布尔属性如是否鉴定、是否可交易、是否已损坏等。你需要用位运算,|,,来提取。例如byte flags data[offset]; bool isIdentified (flags 0x01) ! 0;。调试利器单元测试为你的解析函数编写单元测试使用从游戏中导出的真实、正确的二进制/十六进制数据作为输入验证输出是否符合预期。十六进制转储在解析过程中随时将关键的字节数组BitConverter.ToString(bytes).Replace(“-“, ” “)打印出来与原始数据进行比对。分步解析不要试图一次性解析整个复杂对象。先写代码解析前几个固定长度的字段验证正确后再逐步增加对后续字段尤其是变长字段的解析。处理《热血江湖》这类游戏的二进制数据就像在解一个结构化的谜题。耐心、细致的分析和充分的测试是关键。从简单的已知数据开始逐步构建和完善你的解析库最终你将能游刃有余地驾驭这些隐藏在十六进制字符背后的游戏世界。

相关新闻

Unity RuntimeInitializeOnLoadMethod:掌握运行时初始化的核心机制与工程实践

Unity RuntimeInitializeOnLoadMethod:掌握运行时初始化的核心机制与工程实践

1. 项目概述:为什么我们需要一个“秘密武器”?在Unity项目开发中,尤其是那些架构复杂、模块众多的游戏或应用,我们经常会遇到一个令人头疼的问题:有些初始化代码,到底应该放在哪里执行?是放在第…

2026/10/16 2:31:50 阅读更多 →
从瑞幸CLI看消费级命令行工具的设计与实现

从瑞幸CLI看消费级命令行工具的设计与实现

1. 当咖啡遇上代码:从瑞幸CLI看开发者营销新范式 周一早上,打开终端,敲入 luckin-coffee order latte ,一杯热拿铁已经在配送路上——这听起来像是某个极客的周末玩笑,但瑞幸咖啡似乎正在把它变成现实。最近&#xf…

2026/10/17 4:34:10 阅读更多 →
Godot引擎与Rust语言结合:使用godot-rust构建高性能游戏模块

Godot引擎与Rust语言结合:使用godot-rust构建高性能游戏模块

1. 项目概述:当游戏引擎遇上系统级语言 如果你和我一样,既迷恋Godot引擎的轻量与高效,又对Rust语言的内存安全和性能垂涎三尺,那么 godot-rust 这个项目绝对值得你投入时间。这不是一个简单的“胶水层”,而是一个旨…

2026/10/17 15:38:02 阅读更多 →

最新新闻

AI润色如何重塑网文创作?平台逻辑、技术原理与实战避坑指南

AI润色如何重塑网文创作?平台逻辑、技术原理与实战避坑指南

这几年网文圈有个特别有意思的现象:早两年大家还在争论AI会不会砸了写手的饭碗,现在倒好,平台自己先把AI润色按钮做成了标配。做编辑的朋友跟我吐槽,说后台每天收到大量AI润色稿,有的确实漂亮,有的完全没法…

2026/10/17 16:17:28 阅读更多 →
素颜诗小程序源码解析:从环境搭建到数据层对接的完整指南

素颜诗小程序源码解析:从环境搭建到数据层对接的完整指南

简介:这是一份面向微信小程序开发者与前端学习者的开源项目源码,项目名为「素颜诗」,聚焦诗词与美学场景,提供欣赏与创作诗词的小程序实现。代码以系统开源方式发布,适合希望研究小程序完整工程结构、交互逻辑与数据管…

2026/10/17 16:17:28 阅读更多 →
AI润色与AI生成边界:网文平台态度反转背后的技术原理与实操指南

AI润色与AI生成边界:网文平台态度反转背后的技术原理与实操指南

如果你今天打开任意一家主流网文平台的后台,会看到一件前几年根本不敢想的事:平台不仅没有封杀 AI 润色,有些甚至主动在编辑器里内置了“智能纠错”“AI 优化”按钮。要知道两三年前,各家还在大规模清洗 AI 批量生成的凑数字水文。…

2026/10/17 16:17:28 阅读更多 →
示波器面板按键说明:用TaoToken统一Key打通调试日志与AI辅助解读

示波器面板按键说明:用TaoToken统一Key打通调试日志与AI辅助解读

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 16:17:28 阅读更多 →
【文献分享】PASTA:用酪酰胺-寡核苷酸扩增打通多模态空间生物学分析链路

【文献分享】PASTA:用酪酰胺-寡核苷酸扩增打通多模态空间生物学分析链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 16:17:28 阅读更多 →
Excel数据透视表实战:从源数据清洗到动态汇总的完整指南

Excel数据透视表实战:从源数据清洗到动态汇总的完整指南

简介:这份《Excel数据透视表应用大全》面向需要处理大量业务数据的职场人士与Excel进阶学习者,帮助解决多维度汇总、分类比较与百分比分析等实际分析难题。资源以Word文档形式呈现,共1个doc文件,压缩包约10MB,内容围绕…

2026/10/17 16:16:28 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →