C#【必备技能篇】Hex文件转bin文件的代码实现
文章目錄
- 引言
- 一、需求
- 二、編寫代碼的思路
- 三、代碼實(shí)現(xiàn)【C#】
- 測(cè)試用的hex文件
引言
在了解hex文件格式的基礎(chǔ)上閱讀本文更佳。可閱讀下邊文章:
【HEX文件格式詳解】https://star-302.blog.csdn.net/article/details/119563635
一、需求
將hex文件的內(nèi)容轉(zhuǎn)成按地址順序(從低到高)排列的二進(jìn)制數(shù)據(jù)(bin文件)
二、編寫代碼的思路
整個(gè)過程主要分為三步:
遍歷整個(gè)hex文件,找出最小地址和最大地址(也就是起始地址和結(jié)束地址),算出數(shù)據(jù)長度(數(shù)據(jù)長度=結(jié)束地址-起始地址+1),根據(jù)得到的數(shù)據(jù)長度,分配對(duì)應(yīng)大小的內(nèi)存(開辟一個(gè)數(shù)組);
再次遍歷整個(gè)hex文件,計(jì)算每條數(shù)據(jù)記錄中的起始地址與hex文件起始地址的偏移量,按照偏移量將該條數(shù)據(jù)記錄中的數(shù)據(jù)部分寫入第一步的數(shù)組中。(這樣就實(shí)現(xiàn)了按照從低到高的地址順序排列整個(gè)hex文件的數(shù)據(jù))。
最后只需要將該數(shù)組寫出到文件中即可。
三、代碼實(shí)現(xiàn)【C#】
using System; using System.Globalization; using System.IO; using System.Windows.Forms;namespace WindowsFormsApp1 {/*說明:1.hex內(nèi)容讀取規(guī)則示例: OxO-Ox500【所有字節(jié)內(nèi)容都有】0x0-0x100,0x300-Ox500 【中間有部分地址內(nèi)容缺失,根據(jù)實(shí)際情況默認(rèn)填充Ox00/OxFF】2.擴(kuò)展地址分區(qū)也可刷寫【重點(diǎn)!!!】:hex文件地址分區(qū)的話(segment),此代碼也可以通過*/public partial class Form1 : Form{ public Form1(){InitializeComponent();}public static string hexFilePath = null;//選擇的hex文件路徑public static string binFilePath = null;//保存的bin文件路徑private void btn_OpenFile_Click(object sender, EventArgs e){OpenFileDialog open = new OpenFileDialog();open.RestoreDirectory = true;//open.Filter = "File(*.hex,*.s19)|*.hex;*.s19|BIN File(*.bin)|*.bin";open.Filter = "File(*.hex)|*.hex";open.InitialDirectory = Directory.GetCurrentDirectory();if (DialogResult.OK == open.ShowDialog()){hexFilePath = txt_HexFile.Text = open.FileName;binFilePath = open.FileName.Replace(".hex", ".bin");//確定生成的bin文件路徑}}private void btn_StartConvert_Click(object sender, EventArgs e){try{//【01】獲取hex文件的起始和終止地址(Lowest_Address和Highest_Address) ,并獲取其字節(jié)長度(dataLength)GetAddress(hexFilePath);byte[] buffer = new byte[dataLength]; //創(chuàng)建和hex文件對(duì)應(yīng)長度的字節(jié)數(shù)組//【02】填充數(shù)組內(nèi)容//(情形1:所有地址內(nèi)容都在hex文件中;情形2:在hex文件中有些地址內(nèi)容缺失,需要填充默認(rèn)值“0x00”或“0xFF”)FillData(hexFilePath, ref buffer);//【03】將數(shù)組寫到bin文件WritetoBinFile(binFilePath, buffer, 0, dataLength);MessageBox.Show("轉(zhuǎn)換成功");}catch (Exception ex){MessageBox.Show(ex.Message);}}public static int startAddress = 0;//解析的起始地址public static int endAddress = 0;//解析的終止地址public static int dataLength = 0;//字節(jié)總長度=endAddress-startAddress+1public static string startExtendedAddress = "0000";//第一個(gè)擴(kuò)展地址public static string endExtendedAddress = "0000";//最后一個(gè)擴(kuò)展地址public static bool isFirstExtendedAddress = true;//是否是第一次檢測(cè)到“0x04”public static string startDataAddress = "0000";//第一個(gè)數(shù)據(jù)地址【對(duì)應(yīng)startExtendedAddress】public static string endDataAddress = "0000";//最后一個(gè)數(shù)據(jù)地址【對(duì)應(yīng)endExtendedAddress】public static bool isFirstDataAddress = true;//是否是第一次檢測(cè)到“0x00”public static string lastDataLength = "00";//最后一行的數(shù)據(jù)長度/// <summary>/// 【第1步】獲取hex文件的起始和終止地址,并獲取其字節(jié)長度/// </summary>/// <param name="hexPath"></param>private void GetAddress(string hexPath){FileStream fsRead = new FileStream(hexPath, FileMode.OpenOrCreate, FileAccess.Read);StreamReader HexReader = new StreamReader(fsRead); //讀取數(shù)據(jù)流while (true){string currentLineData = HexReader.ReadLine(); //讀取Hex中一行if (currentLineData == null) { break; } //讀取完畢,退出if (currentLineData.Substring(0, 1) == ":") //判斷首字符是”:”{if (currentLineData.Substring(1, 8) == "00000001"){if (endExtendedAddress == "0000"){endAddress = Convert2Hex(startExtendedAddress + endDataAddress) + Convert2Hex(lastDataLength) - 1;//獲得終止地址dataLength = endAddress - startAddress + 1;}else{endAddress = Convert2Hex(endExtendedAddress + endDataAddress) + Convert2Hex(lastDataLength) - 1;//獲得終止地址dataLength = endAddress - startAddress + 1;}break;} //文件結(jié)束標(biāo)識(shí)string type = currentLineData.Substring(7, 2);switch (type){case "04":if (isFirstExtendedAddress){startExtendedAddress = currentLineData.Substring(9, 4);isFirstExtendedAddress = false;}else{endExtendedAddress = currentLineData.Substring(9, 4);}break;case "00":if (isFirstDataAddress){startDataAddress = currentLineData.Substring(3, 4);startAddress = Convert2Hex(startExtendedAddress + startDataAddress);//獲得起始地址isFirstDataAddress = false;}else{endDataAddress = currentLineData.Substring(3, 4);lastDataLength = currentLineData.Substring(1, 2);//為了獲取最后一行的字節(jié)長度}break;default:break;}}}HexReader.Close();fsRead.Close();}/// <summary>///【第2步】填充數(shù)組內(nèi)容/// </summary>/// <param name="hexPath">hex文件路徑</param>/// <param name="buffer">填充的字節(jié)數(shù)組</param>private void FillData(string hexPath, ref byte[] buffer){int lastLine_EndAddress_Real = startAddress;//上一行結(jié)束的真實(shí)地址【擴(kuò)展地址+數(shù)據(jù)地址】,初始值為hex文件的起始地址int currentLine_StartAddress_Real = 0;//下一行開始的真實(shí)地址【擴(kuò)展地址+數(shù)據(jù)地址】string currentExtendedAddress = "0000";//當(dāng)前擴(kuò)展地址string currentLineDataAddress = "0000";//當(dāng)前數(shù)據(jù)地址int current_BufferIndex = 0;FileStream fsRead = new FileStream(hexPath, FileMode.OpenOrCreate, FileAccess.Read);StreamReader HexReader = new StreamReader(fsRead); //讀取數(shù)據(jù)流while (true){string currentLineData = HexReader.ReadLine(); //讀取Hex中一行if (currentLineData == null) { break; } //讀取完畢,退出if (currentLineData.Substring(0, 1) == ":") //判斷首字符是”:”{//文件結(jié)束標(biāo)識(shí)if (currentLineData.Substring(1, 8) == "00000001"){break;} string type = currentLineData.Substring(7, 2);//讀取當(dāng)前行的類型switch (type){case "04":currentExtendedAddress = currentLineData.Substring(9, 4);break;case "00":currentLineDataAddress = currentLineData.Substring(3, 4);//當(dāng)前數(shù)據(jù)地址currentLine_StartAddress_Real = Convert2Hex(currentExtendedAddress + currentLineDataAddress);//實(shí)際開始地址值//如果這一次的起始地址不等于上一次結(jié)束的下一個(gè)地址,則填充"0x00"if (currentLine_StartAddress_Real != lastLine_EndAddress_Real){for (int i = 0; i < currentLine_StartAddress_Real - lastLine_EndAddress_Real; i++) // 補(bǔ)空位置{byte value = byte.Parse("00", NumberStyles.HexNumber);buffer[current_BufferIndex] = value;current_BufferIndex++;}}int currentLine_DataLength = Convert2Hex(currentLineData.Substring(1, 2));//獲取當(dāng)前行的數(shù)據(jù)長度for (int i = 0; i < currentLine_DataLength; i++){byte value = byte.Parse(currentLineData.Substring(i * 2 + 9, 2), NumberStyles.HexNumber);buffer[current_BufferIndex] = value;current_BufferIndex++;}lastLine_EndAddress_Real = currentLine_StartAddress_Real + currentLine_DataLength;break;default:break;}}}//關(guān)閉Stream和文件HexReader.Close();fsRead.Close();//hex文件最后沒有的byte填充“00”if (buffer.Length > current_BufferIndex){for (int i = 0; i < buffer.Length - current_BufferIndex; i++){byte value = byte.Parse("FF", NumberStyles.HexNumber);buffer[current_BufferIndex + i] = value;}}}/// <summary>/// 【第3步】將數(shù)組寫到bin文件/// </summary>/// <param name="binPath">新建bin文件的路徑</param>/// <param name="buffer">寫入的字節(jié)數(shù)組</param>/// <param name="startIndex">開始索引</param>/// <param name="length">寫入的字節(jié)長度</param>private void WritetoBinFile(string binPath, byte[] buffer, int startIndex, int length){FileStream fsWrite = new FileStream(binPath, FileMode.Create, FileAccess.Write);//如果已存在相同文件名的文件,則刪掉之前的,創(chuàng)建新的文件!!!fsWrite.Write(buffer, startIndex, length);fsWrite.Close();}/// <summary>/// 16進(jìn)制字符串 轉(zhuǎn)化為數(shù)值/// </summary>/// <param name="content">16進(jìn)制字符串</param>/// <returns></returns>private int Convert2Hex(string content){return Convert.ToInt32(content, 16);}} }測(cè)試用的hex文件
鏈接:https://pan.baidu.com/s/1p1aciL2108ABdZcTqZhXew
提取碼:0t67
Test1_noSegment.hex說明:
Test1_noSegment.hex和Test2_haveSegment.hex對(duì)比:
參考:https://blog.csdn.net/ZF_C_CQUPT/article/details/52676716
總結(jié)
以上是生活随笔為你收集整理的C#【必备技能篇】Hex文件转bin文件的代码实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql sha256 示例_SHA2
- 下一篇: C#中$用法