鐵之狂傲

 取回密碼
 註冊
搜尋

切換到指定樓層
1#
要讀取檔案,就我從不會到會的經驗來看,有兩個重點

1.用fstream讀取檔案的方式。

2.了解要讀取的檔案的格式,這點比較重要。


  1. #include <fstream>
  2. //開檔
  3. char Name[]=“01.bmp”; //檔名。注意:這邊的NAME就是下一行的NAME,也就是要讀進去的檔案名稱,這名稱有包括副檔名。
  4. file.open(Name,參數);

  5. //讀檔
  6. file.read(變數,長度);//變數:將讀進去的資料以"變數"這麼名稱儲存。長度:要讀多少長度進去。

  7. 例如:
  8. file.read(line1,3);//這行的意思就是,讀進三個位元組的長度,將這三個位元組儲存在名稱為line1的陣列裡面。當然了,前面要先宣告一個名稱為line1的陣列才行阿。(char line1[32];)

  9. //寫檔
  10. file2.write(變數,長度);
  11. 例如:file.write(line1,3);//將陣列line1裡面的內容前面三個寫出到檔案裡面,詳細請見下面那一個完整的code。
複製代碼

這就是基本的fstream讀檔方式

因為在寫code時,你必須要知道這個檔案的哪幾個資料代表什麼,所以一定要先找出這個檔的組成結構。

之前有人回覆給我這個網址http://blog.pixnet.net/crazycat1130/post/1345538
內容不錯,必看!

除此網站之外,我們助教給我們的PDF也很詳細,也必看!
http://myweb.ncku.edu.tw/~f7495223/BMP_PDF.rar


附上一些fstream的開檔基本用法

  1. 開啟檔案時需使用open()這個函式。其格式如下。
  2. file.open(Name,nMode);
  3.    ios::app:檔案開啟後,檔案指位器直接跳到末端位置,輸入的資料將接在檔案後面。。
  4. &#1048708;ios::in:以輸入的方式處理檔案,這是ifstream的內定值。
  5. &#1048708;ios::out:以輸出的方式處理檔案,這是ofstream的內定值。
  6. &#1048708;ios::trunc:如果檔案已經存在,則內容將被清除。
  7. &#1048708;ios::nocreate:如果檔案不存在,則會有錯誤訊息。
  8. &#1048708;ios::noreplace:如果檔案已經存在,則會有錯誤訊息。
  9. &#1048708;ios::binary:以二進位的形式來處理檔案。

  10. 所以整行可以寫成這樣
  11. file.open(Name,ios::in||ios::binary);
複製代碼

聽同學說處理非純文字的檔案都要加上ios::binary

上面的code"簡化"自助教給的PDF,因為那PDF裡面我看不懂的地方沒有PO上來。


在了解檔案結構之後,建議使用Ultra edit比對之前看到的教學,你會更清楚那是什麼意思!

Ultra edit下載:http://toget.pchome.com.tw/intro/business_wordprocessing/286.html


我覺得最重要的觀念是,「PDF中所寫的圖片資訊,在Ultra edit中,就是按照PDF中介紹的順序一路排列下來的。」(只有我覺得重要吧,同學都很直接這樣想.....)

意思就是,Ultra edit看到的一堆碼,前兩組就是代表檔案形式,接下來四組代表檔案大小,再來兩組是保留區‧‧‧以此類堆。

知道那些碼代表什麼之後,你還要會解讀!

例如:Ultra edit中顯示BMP圖檔最開頭兩組是42 4D,在ASCII(阿斯KEY)中,42=B,4D=M。

再來後兩組是大小的資訊,以一張17462位元組的BMP圖檔為例,第三跟第四組資訊為,36 44。

然後我們開啟小算盤,將它改為工程用的模式(檢視→工程型),在16進位下輸入3644,在轉換到10進位看,卻發現他不是17462。

可是當我們將16進位中的數字改為4436,再將它轉換到10進位,沒錯!它變成17462了。為什麼要從後面開始讀,這我也不知道,反正事實上就是這樣子,而這對我們寫code不會有什麼影響,只是寫出來讓大家輕鬆一下而已。

註:有時會有有一種很詭異的情況:「圖片大小跟儲存的資訊不一樣」。

例如原本我從助教那邊拿到的作業圖片是一張128*128的圖片,整張圖片加上一些檔頭資訊後,這張圖片按照36 44的計算,大小應該是17462位元組,但事實上。剛從助教那邊拿過來時他的大小是17464位元組(右鍵內容看到的),莫名奇妙多出兩個位元組。

原因不明,但是在將圖片用小畫家開啟,隨便做個動作然後復原它,然後另存新檔,檔案大小就變成了17462了(右鍵內容看到的)。
當它的大小是17464時,用Ultra edit看裡面的大小資訊,依然是36 44。


上面就夠讓一個新手頭痛啦!

再來就是整個code怎麼做了。


  1. #include <iostream>
  2. using std::cout;
  3. using std::cin;
  4. using std::endl;

  5. #include <fstream>
  6. using std::fstream;
  7. using std::ios;

  8. typedef unsigned char   BYTE;
  9. typedef unsigned short  WORD;
  10. typedef unsigned long   DWORD;
  11. typedef long            LONG;

  12. void main(){
  13.     fstream file;
  14.         int i,j;
  15.     char fileName[32], RGBQUAD[4][256], PIXEL[128][128],temp[128][128];
  16.    

  17.     WORD bfType;
  18.     DWORD bfSize;
  19.     WORD bfReserved1;
  20.     WORD bfReserved2;
  21.     DWORD bfOffBits;
  22.     DWORD biSize;
  23.     LONG biWidth;
  24.     LONG biHeight;
  25.     WORD biPlanes;
  26.     WORD biBitCount;
  27.     DWORD biCompression;
  28.     DWORD biSizeImage;
  29.     LONG biXPelsPerMeter;
  30.     LONG biYPelsPerMeter;
  31.     DWORD biClrUsed;
  32.     DWORD biClrImportant;

  33.     //將資料從檔案輸入到記憶體
  34.         cout << "Open FileName: ";
  35.     cin >> fileName;

  36.     file.open(fileName, ios::in|ios::binary);
  37.     file.read((char*)&bfType, sizeof(WORD));
  38.     file.read((char*)&bfSize, sizeof(DWORD));
  39.     file.read((char*)&bfReserved1, sizeof(WORD));
  40.     file.read((char*)&bfReserved2, sizeof(WORD));
  41.     file.read((char*)&bfOffBits, sizeof(DWORD));
  42.     file.read((char*)&biSize, sizeof(DWORD));
  43.     file.read((char*)&biWidth, sizeof(LONG));
  44.     file.read((char*)&biHeight, sizeof(LONG));
  45.     file.read((char*)&biPlanes, sizeof(WORD));
  46.     file.read((char*)&biBitCount, sizeof(WORD));
  47.     file.read((char*)&biCompression, sizeof(DWORD));
  48.     file.read((char*)&biSizeImage, sizeof(DWORD));
  49.     file.read((char*)&biXPelsPerMeter, sizeof(LONG));
  50.     file.read((char*)&biYPelsPerMeter, sizeof(LONG));
  51.     file.read((char*)&biClrUsed, sizeof(DWORD));
  52.     file.read((char*)&biClrImportant, sizeof(DWORD));
  53.     file.read(RGBQUAD[0], sizeof(RGBQUAD));
  54.     file.read(PIXEL[0], sizeof(PIXEL));
  55.     file.close();

  56.     //顯示檔案資訊
  57.         cout << "FILE_HEADER\n"
  58.          << "bfType=\t\t"       << bfType       << '\n'
  59.          << "bfSize=\t\t"       << bfSize       << '\n'
  60.          << "bfReserved1=\t"    << bfReserved1  << '\n'
  61.          << "bfReserved2=\t"    << bfReserved2  << '\n'
  62.          << "bfOffBits=\t"      << bfOffBits    << "\n\n"
  63.          << "INFO_HEADER\n"
  64.          << "biSize=\t\t"       << biSize       << '\n'
  65.          << "biWidth=\t"        << biWidth      << '\n'
  66.          << "biHeight=\t"       << biHeight     << '\n'
  67.          << "biPlanes=\t"       << biPlanes     << '\n'
  68.          << "biBitCount=\t"     << biBitCount   << '\n'
  69.          << "biCompression=\t"  << biCompression    << '\n'
  70.          << "biSizeImage=\t"    << biSizeImage      << '\n'
  71.          << "biXPelsPerMeter="  << biXPelsPerMeter  << '\n'
  72.          << "biYPelsPerMeter="  << biYPelsPerMeter  << '\n'
  73.          << "biClrUsed=\t"      << biClrUsed        << '\n'
  74.          << "biClrImportant=\t" << biClrImportant   << "\n\n";

  75.                 //將圖片資訊暫存到TEMP裡面
  76.                 for(i=127;i>=0;i--){
  77.                         for(j=127;j>=0;j--){
  78.                                 temp[i][j]=PIXEL[i][j];
  79.                                 }
  80.                         }
  81.                         //將資訊反轉180度
  82.                 for(i=0;i<=127;i++){
  83.                         for(j=0;j<=127;j++){
  84.                                 PIXEL[127-i][127-j]=temp[i][j];
  85.                                 }
  86.                         }
  87.                 //將資料從記憶體輸出到檔案       
  88.                 cout << "輸入旋轉後儲存的名稱:\t";
  89.             cin >> fileName;

  90.                 file.open(fileName, ios::out|ios::binary);
  91.                 file.write((char*)&bfType, sizeof(WORD));
  92.                 file.write((char*)&bfSize, sizeof(DWORD));
  93.                 file.write((char*)&bfReserved1, sizeof(WORD));
  94.                 file.write((char*)&bfReserved2, sizeof(WORD));
  95.                 file.write((char*)&bfOffBits, sizeof(DWORD));
  96.                 file.write((char*)&biSize, sizeof(DWORD));
  97.                 file.write((char*)&biWidth, sizeof(LONG));
  98.                 file.write((char*)&biHeight, sizeof(LONG));
  99.                 file.write((char*)&biPlanes, sizeof(WORD));
  100.                 file.write((char*)&biBitCount, sizeof(WORD));
  101.                 file.write((char*)&biCompression, sizeof(DWORD));
  102.                 file.write((char*)&biSizeImage, sizeof(DWORD));
  103.                 file.write((char*)&biXPelsPerMeter, sizeof(LONG));
  104.                 file.write((char*)&biYPelsPerMeter, sizeof(LONG));
  105.                 file.write((char*)&biClrUsed, sizeof(DWORD));
  106.                 file.write((char*)&biClrImportant, sizeof(DWORD));
  107.                 file.write(RGBQUAD[0], sizeof(RGBQUAD));
  108.                 file.write(PIXEL[0], sizeof(PIXEL));
  109.                 file.close();
複製代碼


因為我要顯示檔案資訊

所以中間那一段比較複雜

一般要做特效的話,不必將中間檔案資訊的地方每一段都讀出來,直接將它讀做一個headfile就可以了。


要讀取的圖檔記得要放在你的專案所儲存的資料夾。

差不多就這樣吧。拜拜
 
轉播0 分享0 收藏0

回覆 使用道具 檢舉

這是我原本發在微風的東西

現在轉過來

應該可以讓C++新手知道學到的東西有這種很好玩的應用方法
 

回覆 使用道具 檢舉

不推不是人啊
 

回覆 使用道具 檢舉

程式寫的不錯,推一下
另有二點建議

1. 讀入BMP檔頭資訊的部份可以研究一下stuct的用法
2. 看來這程式是假設開的檔案是BMP,不是BMP的情況可以加點檢查,避免出錯

回覆 使用道具 檢舉

你需要登入後才可以回覆 登入 | 註冊

存檔|手機版|聯絡我們|新聞提供|鐵之狂傲

GMT+8, 24-12-25 14:13 , Processed in 0.020503 second(s), 20 queries , Gzip On.

回頂部