日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# 学习笔记(12)hex文件转bin文件小工具

發(fā)布時間:2025/4/16 C# 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 学习笔记(12)hex文件转bin文件小工具 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

C# 學(xué)習(xí)筆記(12)hex文件轉(zhuǎn)bin文件小工具

hex文件格式

hex文件格式網(wǎng)上有很多
我這里參考HEX文件格式詳解https://blog.csdn.net/weixin_39752827/article/details/81477686

編寫hex2bin類

hex轉(zhuǎn)bin文件的方法很多,但是在做bootLoader工具時,只能接受bin文件就很煩,就有了將hex轉(zhuǎn)bin集成到自己工具里的想法。
首先去github找了一下,避免重復(fù)造輪子,發(fā)現(xiàn)了兩個不錯的c#示例
Hex2Bin https://github.com/x893/Hex2Bin
STM32-IAP-HEX-Merge https://github.com/SmartElec/STM32-IAP-HEX-Merge
但是不太滿意,剛好又在學(xué)習(xí)c#,就動手自己造了個輪子

using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks;namespace CSharp_Hex2Bin {/// <summary>/// hex文件轉(zhuǎn)bin文件 /// hex格式解析:<0x3a>[數(shù)據(jù)長度1Byte][數(shù)據(jù)地址2Byte][數(shù)據(jù)類型1Byte][數(shù)據(jù)nByte][校驗1Byte]<0x0d><0x0a>/// </summary>public static class MyHex2Bin{/// <summary>/// hex文件段信息結(jié)構(gòu)體/// </summary>public class Section{public uint startAddr = new uint();public uint endAddr = new uint();public List<byte> data = new List<byte>();public string filePath;}/// <summary>/// hex 數(shù)據(jù)類型/// </summary>enum INTEL_COMMAND : byte{UNKNOWN = 0xFF,/// <summary>/// Data Record 數(shù)據(jù)/// </summary>DATA = 0x00,/// <summary>/// End of File Record 文件結(jié)束標(biāo)志/// </summary>EOF = 0x01,/// <summary>/// Extended Segment Address Record 延伸段地址/// </summary>EXT_SEGMENT_ADDR = 0x02,/// <summary>/// Start Segment Address Record 起始延伸地址/// </summary>SEGMENT_ADDR = 0x03,/// <summary>/// Extended Linear Address Record 擴展線性地址 也就是基地址/// </summary>EXTEND_ADDR = 0x04,/// <summary>/// Start Linear Address Record 程序起始地址也就是程序入口地址(main)/// </summary>LINEAR_ADDR = 0x05,DATA_LOOP = 0x10}/// <summary>/// 根據(jù)hex文件生成bin文件, 不管hex文件是否有問題 /// </summary>/// <param name="outBinFilePath">bin文件路徑</param>/// <param name="encoding">hex文件編碼格式</param>/// <param name="ignoreByte">占位符 空白的地址填</param>/// <param name="sections">hex文件信息</param>/// <param name="log">日志信息</param>/// <param name="errSections">有問題的地址塊</param>/// <param name="inHexFilePath">hex文件路徑</param>public static void Conver(string outBinFilePath, Encoding encoding, byte ignoreByte, ref List<Section> sections, out string log, ref List<Section> errSections, params string[] inHexFilePath){LoadHex(encoding, ref sections, out log, ref errSections, inHexFilePath);WriteBinFile(outBinFilePath, ignoreByte, sections);}/// <summary>/// 根據(jù)hex文件生成bin文件, 不管hex文件是否有問題 /// </summary>/// <param name="outBinFilePath">bin文件路徑</param>/// <param name="inHexFilePath">hex文件路徑</param>public static void Conver(string outBinFilePath, params string[] inHexFilePath){List<Section> sections = new List<Section>();List<Section> errSections = new List<Section>();Conver(outBinFilePath, Encoding.Default, 0, ref sections, out string log, ref errSections, inHexFilePath);}/// <summary>/// 根據(jù)hex文件生成bin文件, 不管hex文件是否有問題 /// </summary>/// <param name="inHexFilePath">hex文件路徑</param>public static void Conver(params string[] inHexFilePath){Conver(inHexFilePath[0], inHexFilePath);}/// <summary>/// 將hex文件讀到內(nèi)存中/// </summary>/// <param name="encoding">hex文件編碼格式</param>/// <param name="sections">hex文件信息</param>/// <param name="log">日志</param>/// <param name="errSections">有問題的地址塊</param>/// <param name="inHexFilePath">hex文件路徑</param>public static void LoadHex(Encoding encoding, ref List<Section> sections, out string log, ref List<Section> errSections, params string[] inHexFilePath){//加載hex文件LoadHex(encoding, ref sections, out log, inHexFilePath);//檢查地址沖突if (!CheckAddr(sections, out string str, ref errSections)){log += str;}}/// <summary>/// 將hex文件讀到內(nèi)存中/// </summary>/// <param name="encoding">hex文件編碼格式</param>/// <param name="sections">hex文件信息</param>/// <param name="log">日志</param>/// <param name="inHexFilePath">hex文件路徑</param>public static void LoadHex(Encoding encoding, ref List<Section> sections, out string log, params string[] inHexFilePath){log = "";foreach (var item in inHexFilePath){if (!string.IsNullOrWhiteSpace(item)){//文件存在并且以.hex結(jié)尾if (File.Exists(item) && Path.GetExtension(item).ToLower().Equals(".hex")){#region 解析一個hex文件//讀取hex文件string[] hexFileAllLines = File.ReadAllLines(item, encoding);List<Section> tempSections = new List<Section>();uint extend_address = 0, start_address = 0, segment_address = 0, linear_address = 0;uint count = 0, address = 0;byte dataType = 0;INTEL_COMMAND command = INTEL_COMMAND.UNKNOWN;for (int line = 0; line < hexFileAllLines.Length; line++){bool fail = false;string hexFileLine = hexFileAllLines[line];//hex文件每行最少11個字符并且以":"起始if (hexFileLine.Length >= 11 && hexFileLine.StartsWith(":") && CheckSum(hexFileLine)){#region 解析一行hex文件 獲取其長度、地址、數(shù)據(jù)類型、校驗和信息fail |= !uint.TryParse(hexFileLine.Substring(1, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out count);fail |= !uint.TryParse(hexFileLine.Substring(3, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address);fail |= !byte.TryParse(hexFileLine.Substring(7, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out dataType);command = (INTEL_COMMAND)dataType;if (fail){log += "文件: " + item + " 第" + line + "行\(zhòng)r\n" + hexFileLine + "\r\n不符合hex文件格式!解析失敗\r\n";break;}#endregion}else{log += "文件: " + item + " 第" + line + "行\(zhòng)r\n" + hexFileLine + "\r\n不符合hex文件格式!\r\n";continue;}switch (command){case INTEL_COMMAND.EOF:sections.AddRange(tempSections);log += "文件: " + item + " 解析完成 共解析:" + line + "行\(zhòng)r\n";line = hexFileAllLines.Length;break;case INTEL_COMMAND.DATA:#region 正常數(shù)據(jù)接收case INTEL_COMMAND.DATA_LOOP:int idx = 9; //hex文件 第九個字符開始才是數(shù)據(jù)if (tempSections.Count > 0){if (string.IsNullOrEmpty(tempSections[tempSections.Count - 1].filePath)){tempSections[tempSections.Count - 1].startAddr = segment_address + extend_address + address;tempSections[tempSections.Count - 1].endAddr = tempSections[tempSections.Count - 1].startAddr;tempSections[tempSections.Count - 1].filePath = item;}else if ((tempSections[tempSections.Count - 1].endAddr - (segment_address + extend_address) + 1) != address){tempSections.Add(new Section());tempSections[tempSections.Count - 1].startAddr = segment_address + extend_address + address;tempSections[tempSections.Count - 1].endAddr = tempSections[tempSections.Count - 1].startAddr;tempSections[tempSections.Count - 1].filePath = item;}}for (; !fail && count > 0; --count){fail = !byte.TryParse(hexFileLine.Substring(idx, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out byte data);if (!fail){tempSections[tempSections.Count - 1].data.Add(data);tempSections[tempSections.Count - 1].endAddr = segment_address + extend_address + address;}else{fail = true;}idx += 2;address++;}break;#endregioncase INTEL_COMMAND.EXT_SEGMENT_ADDR:#region 延伸段地址解析if (count != 2 || hexFileLine.Length != 15){fail = true;log += string.Format("文件: {0} 第 {1} 行: {2} 延伸段地址解析錯誤\r\n", item, line.ToString(), hexFileLine);}else{fail |= !uint.TryParse(hexFileLine.Substring(9, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out segment_address);if (fail)log += string.Format("文件: {0} 第 {1} 行:{2} 延伸段地址解析錯誤\r\n", item, line.ToString(), hexFileLine);else{segment_address <<= 4;tempSections.Add(new Section());}}break;#endregioncase INTEL_COMMAND.SEGMENT_ADDR:#region 起始段地址解析if (count != 4){log += string.Format("文件: {0} 第 {1} 行: {2} 起始段地址解析錯誤\r\n", item, line.ToString(), hexFileLine);}else{fail |= !uint.TryParse(hexFileLine.Substring(9, 8), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out start_address);if (fail)log += string.Format("文件: {0} 第 {1} 行: {2} 起始段地址解析錯誤\r\n", item, line.ToString(), hexFileLine);elselog += string.Format("文件: {0} 第 {1} 行: 起始段地址解析成功: 0x{2:X}\r\n", item, line.ToString(), start_address);}break;#endregioncase INTEL_COMMAND.EXTEND_ADDR:#region 擴展段地址解析if (hexFileLine.Length != 15){log += string.Format("文件: {0} 第 {1} 行: {2} 擴展段地址解析錯誤\r\n", item, line.ToString(), hexFileLine);fail = true;}else{fail |= !uint.TryParse(hexFileLine.Substring(9, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out extend_address);if (fail){log += string.Format("文件: {0} 第 {1} 行: {2} 擴展段地址解析錯誤\r\n", item, line.ToString(), hexFileLine);}else{extend_address = extend_address << 16;tempSections.Add(new Section());}}break;#endregioncase INTEL_COMMAND.LINEAR_ADDR:#region 程序起始地址也就是程序入口地址(main)解析if (count != 4){log += string.Format("文件: {0} 第 {1} 行: {2} 程序起始地址解析錯誤\r\n", item, line.ToString(), hexFileLine);}else{fail |= !uint.TryParse(hexFileLine.Substring(9, 8), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out linear_address);if (fail)log += string.Format("文件: {0} 第 {1} 行: {2} 程序起始地址解析錯誤\r\n", item, line.ToString(), hexFileLine);elselog += string.Format("文件: {0} 第 {1} 行: 程序起始地址解析成功: 0x{2:X}\r\n", item, line.ToString(), linear_address);}break;#endregiondefault:log += "文件: " + item + " 第" + line + "行\(zhòng)r\n" + hexFileLine + "\r\n不符合hex文件格式!\r\n";fail = true;break;}if (fail){log += "文件: " + item + " 第" + line + "行\(zhòng)r\n" + hexFileLine + "\r\n不符合hex文件格式!\r\n";break;}}#endregion}else{log += "文件: " + item + "不存在或不是.hex文件!\r\n";}}}}/// <summary>/// 校驗hex文件一行數(shù)據(jù) /// </summary>/// <param name="hexLine">hex一行數(shù)據(jù)</param>/// <returns>true 校驗成功</returns>public static bool CheckSum(string hexLine){bool fail = false;byte sum = 0;byte data = 0;for (int i = 1; i < hexLine.Length - 2; i += 2){fail |= !byte.TryParse(hexLine.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data);sum += data;}fail |= !byte.TryParse(hexLine.Substring(hexLine.Length - 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data);if ((byte)(0x100 - sum) == data && !fail){return true;}return false;}/// <summary>/// 檢查地址是否有OK/// </summary>/// <param name="sections"></param>/// <param name="log">日志信息</param>/// <param name="errSections">有問題的地址塊</param>/// <returns>true 地址信息沒問題</returns>public static bool CheckAddr(List<Section> sections, out string log, ref List<Section> errSections){log = "";bool err = true;//排序sections.Sort((x, y) => x.startAddr.CompareTo(y.startAddr));//每個存儲塊 數(shù)據(jù)個數(shù)和地址信息是否一致for (int i = 0; i < sections.Count; i++){if (sections[i].startAddr + sections[i].data.Count -1 != sections[i].endAddr){errSections.Add(sections[i]);log += string.Format("文件: {2} 地址塊:0x{0:x8}--0x{1:x8} 數(shù)據(jù)出錯\r\n", sections[i].startAddr, sections[i].endAddr, sections[i].filePath);err = false;}}//存儲塊之間是否有重疊for (int i = 1; i< sections.Count; i++){if(sections[i].startAddr < sections[i-1].endAddr){errSections.Add(sections[i-1]);errSections.Add(sections[i]);log += string.Format("文件: {4} 和 文件: {5} 地址沖突:0x{0:x8}--0x{1:x8} 和 0x{2:x8}--0x{3:x8}\r\n", sections[i - 1].startAddr, sections[i - 1].endAddr, sections[i].startAddr, sections[i].endAddr, sections[i - 1].filePath, sections[i].filePath);err = false;}}return err;}/// <summary>/// 將地址塊數(shù)據(jù)寫入到文件中/// </summary>/// <param name="outBinFilePath">輸出文件路徑</param>/// <param name="ignoreByte">占位符 空白的地址填</param>/// <param name="sections">hex文件塊信息</param>public static void WriteBinFile(string outBinFilePath, byte ignoreByte, List<Section> sections){uint startAddr = sections[0].startAddr;int size = (int)(sections[sections.Count - 1].endAddr - startAddr) + 1;if(size > 1024*1024*20){return;}byte[] binFile = new byte[size];ArrayList.Repeat(ignoreByte, size).CopyTo(binFile);//將地址塊信息寫入到內(nèi)存數(shù)組中foreach (var item in sections){item.data.ToArray().CopyTo(binFile, item.startAddr - startAddr);}if (Path.GetExtension(outBinFilePath).ToLower() != ".bin"){outBinFilePath = Path.ChangeExtension(outBinFilePath, ".bin");}File.WriteAllBytes(outBinFilePath, binFile);}/// <summary>/// 將地址塊數(shù)據(jù)寫入到文件中/// </summary>/// <param name="sections">hex文件塊信息</param>public static void WriteBinFile(List<Section> sections){WriteBinFile(sections[0].filePath, 0xff, sections);}} }

軟件使用

根據(jù)上面的hex2bin類,編寫了一個簡單的示例,hex2bin小工具

  • 可以將hex文件拖拽到軟件打開
  • 可以將未指定的flash地址填充未0
  • 可以分析hex文件地址信息

  • 源碼地址 https://github.com/mian2018/CSharp_Hex2Bin

    總結(jié)

    以上是生活随笔為你收集整理的C# 学习笔记(12)hex文件转bin文件小工具的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。