生活随笔
收集整理的這篇文章主要介紹了
C# 学习笔记(12)hex文件转bin文件小工具
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C# 學習筆記(12)hex文件轉bin文件小工具
hex文件格式
hex文件格式網上有很多
我這里參考HEX文件格式詳解https://blog.csdn.net/weixin_39752827/article/details/81477686
編寫hex2bin類
hex轉bin文件的方法很多,但是在做bootLoader工具時,只能接受bin文件就很煩,就有了將hex轉bin集成到自己工具里的想法。
首先去github找了一下,避免重復造輪子,發現了兩個不錯的c#示例
Hex2Bin https://github.com/x893/Hex2Bin
STM32-IAP-HEX-Merge https://github.com/SmartElec/STM32-IAP-HEX-Merge
但是不太滿意,剛好又在學習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
{public static class MyHex2Bin{public class Section{public uint startAddr
= new uint();public uint endAddr
= new uint();public List<byte> data
= new List<byte>();public string filePath
;}enum INTEL_COMMAND : byte{UNKNOWN
= 0xFF,DATA
= 0x00,EOF
= 0x01,EXT_SEGMENT_ADDR
= 0x02,SEGMENT_ADDR
= 0x03,EXTEND_ADDR
= 0x04,LINEAR_ADDR
= 0x05,DATA_LOOP
= 0x10}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
);}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
);}public static void Conver(params string[] inHexFilePath
){Conver(inHexFilePath
[0], inHexFilePath
);}public static void LoadHex(Encoding encoding
, ref List<Section> sections
, out string log
, ref List<Section> errSections
, params string[] inHexFilePath
){LoadHex(encoding
, ref sections
, out log
, inHexFilePath
);if (!CheckAddr(sections
, out string str
, ref errSections
)){log
+= str
;}}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
)){if (File
.Exists(item
) && Path
.GetExtension(item
).ToLower().Equals(".hex")){#region 解析一個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
];if (hexFileLine
.Length
>= 11 && hexFileLine
.StartsWith(":") && CheckSum(hexFileLine
)){#region 解析一行hex文件 獲取其長度、地址、數據類型、校驗和信息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
+ "行\r\n" + hexFileLine
+ "\r\n不符合hex文件格式!解析失敗\r\n";break;}#endregion}else{log
+= "文件: " + item
+ " 第" + line
+ "行\r\n" + hexFileLine
+ "\r\n不符合hex文件格式!\r\n";continue;}switch (command
){case INTEL_COMMAND
.EOF
:sections
.AddRange(tempSections
);log
+= "文件: " + item
+ " 解析完成 共解析:" + line
+ "行\r\n";line
= hexFileAllLines
.Length
;break;case INTEL_COMMAND
.DATA
:#region 正常數據接收case INTEL_COMMAND
.DATA_LOOP
:int idx
= 9; 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
+ "行\r\n" + hexFileLine
+ "\r\n不符合hex文件格式!\r\n";fail
= true;break;}if (fail
){log
+= "文件: " + item
+ " 第" + line
+ "行\r\n" + hexFileLine
+ "\r\n不符合hex文件格式!\r\n";break;}}#endregion}else{log
+= "文件: " + item
+ "不存在或不是.hex文件!\r\n";}}}}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;}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
));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} 數據出錯\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
;}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
);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
);}public static void WriteBinFile(List<Section> sections
){WriteBinFile(sections
[0].filePath
, 0xff, sections
);}}
}
軟件使用
根據上面的hex2bin類,編寫了一個簡單的示例,hex2bin小工具
可以將hex文件拖拽到軟件打開可以將未指定的flash地址填充未0可以分析hex文件地址信息
源碼地址 https://github.com/mian2018/CSharp_Hex2Bin
總結
以上是生活随笔為你收集整理的C# 学习笔记(12)hex文件转bin文件小工具的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。