CFileDialog類與16進制格式的dat檔案
要将資料儲存為.dat檔案,而且是16進制的數字,怎麼儲存?
要讀取.dat檔案,檔案是16進制的,怎麼讀取?
用CFileDialog類可以得到【儲存】和【打開】的對話框,具體怎麼儲存和讀取,需要我們自己寫代碼了。這裡,和大家分享一下,怎麼儲存16進制的檔案到.dat中?怎樣從.dat中讀取你儲存的16進制數字?
對于讀取到的這些資料,你想做什麼,可以因人而異。您可以在看懂本篇文章的基礎上,舉一反三。
本人也是菜鳥,也是參考了很多論壇上高手的代碼。代碼雖然能通過編譯,可能不是最好的。歡迎大家提出意見。
一、儲存16進制數字的.dat檔案:
1 // 檔案的儲存
2 // 通過CFileDialog 類,儲存檔案
3 CFileDialog fileDlg(FALSE, "dat", "btypetb");
4 fileDlg.m_ofn.lpstrTitle="請保持設定";
5 fileDlg.m_ofn.lpstrFilter=".dat files(*.dat)*.dat";
6
7 // 獲得相對路徑(網上找的的這個方法)
8 // 先擷取目前正在運作的程式的路徑,然後将該路徑拿來自己用 。
9 TCHAR szFilePath[MAX_PATH + 1];
10 GetModuleFileName(NULL, szFilePath, MAX_PATH);
11 (_tcsrchr(szFilePath, _T('\')))[1] = 0;
12 CString strtemp = szFilePath;
13 fileDlg.m_ofn.lpstrInitialDir = strtemp;
14
15 // 定義fpFile檔案指針
16 FILE *fpFile;
17
18 // 如果使用者點選了儲存按鈕,則執行if語句内的操作
19 if (IDOK == fileDlg.DoModal())
20 {
21 // 擷取使用者輸入的檔案名。有2種方法
22 CString fileName = fileDlg.GetFileName();
23 // CString fileName = fileDlg.m_ofn.lpstrFileTitle;
24
25 // fopen的第一個參數是帶路徑的檔案名。
26 if ((fpFile = fopen(strtemp+"\"+fileName, "w+b")) == NULL)
27 return ;
28 fwrite (datBuffer, 2 + m_DevCounts * 2, 1, fpFile);
29 fclose(fpFile);
30 }
雖然代碼裡面有注釋,我這裡還是再解釋一部分代碼:
1.代碼第3行,第一個參數false,表示我們需要一個【儲存】的對話框。如果傳遞true,那麼你将得到【打開】的對話框。第二個參數是儲存檔案預設的檔案格式,這裡是dat格式。第三個參數比較重要了,是你預設的檔案名。參數傳遞的個數,不是固定的,你可以傳入1個參數,也可以傳入多個參數,根據個人需要而定。更多解釋,您可以參考MSDN。
2.代碼第5行,這是設定格式過濾器。我也是參考孫鑫的《VC++深入詳解》第12章中提到的檔案過濾器來做的。下面的代碼是教程中的代碼,您可以自己手動設定幾次,弄懂之後,修改為自己需要的就可以了。
View Code
3.代碼第7行到第13行,是參考了網上一位高手的回帖。
4.注意第26行代碼裡面的參數。這裡是設定為二進制的寫。您可以參考MSDN了解跟多資訊。
5.看第28行代碼。這是我們的重點。檔案操作3部曲:1.打開檔案;2.Write/Read檔案;3.關閉檔案。
第28行代碼中,第一個參數,是儲存了這些16進制數字的數組,第2個參數,是數組的大小(為什麼我的第二個參數是這樣樣子的,您就不必糾結了。這是我程式中的實際傳遞過來的參數。您可以根據實際情況來決定您的數組大小。);其他參數,參考MSDN。
datBuffer是這樣定義的:BYTE datBuffer[200]; // 數組長度根據您個人實際來設定。
BYTE 是 unsigned char 類型 // 在你進行類型轉換的時候,會很有用
為什麼定義為BYTE就是能儲存16進制數字了,其實我也不太清楚。
我也是在網上參考高手的代碼,才實作上述功能的。剛才在網上又搜了一下,這裡有個将BYTE和16進制之間的關系的文章,可以看看。
http://www.360doc.com/content/11/0222/22/4780948_95250828.shtml
回到文章中來,我們就這麼一 Write,就能成功生成16進制的.dat檔案了。哈哈,是不是感覺特厲害。。。。。。
在成功的同時,我們也應該知道,其實還是有一些知識點沒有消化。。。歡迎高手指點。
補充一點:
.dat存儲的時候,是以BYTE來存儲的。說得通俗點,就是unsigned char 類型來存儲的。
而我的原始資料是int類型。。。将int轉為16進制的BYTE。這裡,不需要用到什麼函數。
直接,強制類型轉換。即可。不需要想太多、太複雜。
int a1=10, a2=192;
BYTE arr[4] = {0};
arr[0] = (unsigned char)a1;
arr[1] = (unsigned char)a2;
arr[2] = 0xaa;
//上面的指派代碼都是合法的。
// 這樣做就很好了。還需要啥函數來轉換。。
// 活學活用啊。。。我當時鑽牛角尖了。
二、讀取16進制數字的.dat檔案:
1 CFileDialog fileDlg(TRUE);
2 fileDlg.m_ofn.lpstrTitle="打開我的dat檔案";
3 fileDlg.m_ofn.lpstrFilter=".dat files(*.dat)*.dat";
4
5 // 獲得相對路徑(網上找的的這個方法)
6 // 先擷取目前正在運作的程式的路徑,然後将該路徑拿來自己用 。
7 TCHAR szFilePath[MAX_PATH + 1];
8 GetModuleFileName(NULL, szFilePath, MAX_PATH);
9 (_tcsrchr(szFilePath, _T('\')))[1] = 0;
10 CString strtemp = szFilePath;
11 fileDlg.m_ofn.lpstrInitialDir = strtemp;
12
13 // 定義fpFile檔案指針
14 FILE *fpFile;
15
16 if (IDOK == fileDlg.DoModal())
17 {
18 long Filelen;
19 // 注意細節
20 unsigned char* buffer;
21
22 CString fileName = fileDlg.GetPathName();
23
24 if ((fpFile = fopen(fileName, "rb")) == NULL)
25 return ;
26
27 // 檔案指針到檔案尾
28 fseek(fpFile, 0, SEEK_END);
29 // 讀取檔案長度
30 Filelen = ftell(fpFile);
31 // 配置設定記憶體
32 // 按檔案長度申請記憶體空間
33 buffer = (unsigned char*)malloc(Filelen);
34
35 // 檔案指針指到檔案頭
36 fseek(fpFile, 0, SEEK_SET);
37 // 讀取檔案到申請的記憶體
38 fread(buffer, 1, Filelen, fpFile);
39 fclose(fpFile);
40
41 // 到這裡,其實buffer裡面已經存放了你需要的資料,你可以做你需要的操作了。
42 // 這裡,将讀取的16進制數字,在MessageBox中顯示出來。
43 CString strResult;
44 for(int j=0; j<Filelen; j++)
45 {
46 CString s = "";
47 s.Format("%2.2x ", buffer[j]);
48 strResult += s;
49 }
50
51 MessageBox(strResult);
52 }
1.代碼第1行,這裡傳遞的參數是TRUE。表示,我們需要一個【打開】的對話框。
2.代碼第20行,我們定義的是 unsgined char* 類型的變量。
3.從代碼第28行開始,是重點了。
4.在代碼第24行中,設定了為二進制打開。
5.第38行代碼,将資料讀入到buffer中了。到此,你已經得到你想要的16進制數字了。你想怎麼處理,可以根據實際情況來實際操作。這裡再說一次,buffer定義的是unsigned char*類型,在進行強制類型轉換的時候,會有用的。
6.在這裡,我們想将.dat檔案裡的16進制數字在MessageBox對話框中顯示出來,我們可以看第44行的代碼。
補充:
如果你想将這些16進制數字顯示出來的話,第41行到第51行的代碼可以實作此功能。
如果你想将讀取的16進制數字用作其他用途,個人是這麼了解的。
通過第38行的代碼,你的buffer數組中,已經存放了16進制的數字了。
16進制數字對我來說,沒多大用。(至少我目前程式中沒有涉及到這方面的問題)
我當時是這麼做的,将16進制的數字轉換為整型的數字。整型是大家都熟悉的類型,然後你就可以想幹什麼就幹什麼了。
(如果您在數值直接的轉換方面遇到了一些問題,個人建議還是多看看這些類型的定義(一般,C++基礎教程裡面都會講到的,溫故而知新)。比如BYTE其實是unsigned char類型,char和int之間是可以互相轉換的,但是要注意char的範圍,也要知道,unsgined char 和 char 作用的範圍不同,小心資料丢失哦。)
int Num1, Num2;
Num1 = buffer[0];
Num2 = buffer[1];
總結:感謝,感謝網上各位高手。
這裡是幾個值得參考的文章:
http://bbs.csdn.net/topics/300048398
http://bbs.csdn.net/topics/320263449