二進制文件的讀寫(C語言,C++)

首先是用C語言實現:

我們一共要用到三個函數,fopen,fread,fwrite。二進制讀寫的順序是用fopen以二進制方式打開讀寫文件,然後使用fread和fwrite兩個函數將數據寫入二進制文件中。下面我們看看一個拷貝程序的源碼:  ( Copy.c )

#include <stdio.h>

#include <stdlib.h>

#define MAXLEN  1024

int main(int argc, char *argv[]){

      if ( argc < 3 ) {

               printf("usage: %s %s/n", argv[0], "infile outfile");

              exit(1);

      }

       FILE * outfile, *infile;

       outfile = fopen(argv[2], "wb" );

       infile = fopen(argv[1], "rb");

       unsigned char buf[MAXLEN];

       if( outfile == NULL || infile == NULL ) {

               printf("%s, %s", argv[1], "not exit/n");

               exit(1);

       }   

      int rc;

       while( (rc = fread(buf,sizeof(unsigned char), MAXLEN,infile)) != 0 )  {

               fwrite( buf, sizeof( unsigned char ), rc, outfile ); 

        

fclose(infile);

fclose(outfile);

       system("PAUSE"); 

       return 0;

}
現在來講講這個程序,這個程序的作用就是將文件1的內容直接拷貝到文件2中,注意fread的返回值,這個值需要在fwrite的時候將會用到。

後面是關於fopen,fread,fwrite三個函數的詳細說明。

fopen(打開文件)

相關函數
open,fclose
表頭文件
#include<stdio.h>
定義函數
FILE * fopen(const char * path, const char * mode);
函數說明
參數path字符串包含欲打開的文件路徑及文件名,參數mode字符串則代表着流形態。
mode有下列幾種形態字符串:
r : 打開只讀文件,該文件必須存在。
r+ : 打開可讀寫的文件,該文件必須存在。
w  : 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則建立該文件。
w+ : 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則建立該文件。
a  : 以附加的方式打開只寫文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。
a+ : 以附加方式打開可讀寫的文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。
上述的形態字符串都可以再加一個b字符,如rb、w+b或ab+等組合,加入b 字符用來告訴函數庫打開的文件爲二進制文件,而非純文字文件。不過在POSIX系統,包含Linux都會忽略該字符。由fopen()所建立的新文件會具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)權限,此文件權限也會參考umask值。
返回值
文件順利打開後,指向該流的文件指針就會被返回。若果文件打開失敗則返回NULL,並把錯誤代碼存在errno 中。
附加說明
一般而言,開文件後會作一些文件讀取或寫入的動作,若開文件失敗,接下來的讀寫動作也無法順利進行,所以在fopen()後請作錯誤判斷及處理。
範例
#include<stdio.h>
main()
{
      FILE * fp;
      fp=fopen("noexist", "a+");
      if( fp == NULL) return;
      fclose(fp);
}

fread(從文件流讀取數據)

相關函數
fopen,fwrite,fseek,fscanf
表頭文件
#include<stdio.h>
定義函數
size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream);
函數說明
fread()用來從文件流中讀取數據。參數stream爲已打開的文件指針,參數ptr 指向欲存放讀取進來的數據空間,讀取的字符數以參數size*nmemb來決定。Fread()會返回實際讀取到的nmemb數目,如果此值比參數nmemb 來得小,則代表可能讀到了文件尾或有錯誤發生,這時必須用feof()或ferror()來決定發生什麼情況。
返回值
返回實際讀取到的nmemb數目。
附加說明

 
範例
#include<stdio.h>
#define nmemb 3
struct test
{
      char name[20];
      int size;
}s[nmemb];

main()
{
      FILE * stream;
      int i;
      stream = fopen("/tmp/fwrite", "r");
      fread(s, sizeof(struct test), nmemb, stream);
      fclose(stream);
      for(i=0; i<nmemb; i++)
            printf("name[%d]=%-20s:size[%d]=%d/n", i, s[i].name, i, s[i].size);
}
執行
name[0]=Linux!  size[0]=6
name[1]=FreeBSD!  size[1]=8
name[2]=Windows2000  size[2]=11

fwrite(將數據寫至文件流)

相關函數
fopen,fread,fseek,fscanf
表頭文件
#include<stdio.h>
定義函數
size_t fwrite(const void * ptr, size_t size, size_t nmemb, FILE * stream);
函數說明
fwrite()用來將數據寫入文件流中。參數stream爲已打開的文件指針,參數ptr 指向欲寫入的數據地址,總共寫入的字符數以參數size*nmemb來決定。Fwrite()會返回實際寫入的nmemb數目。
返回值
返回實際寫入的nmemb數目。
範例
#include<stdio.h>
#define set_s (x,y) {strcoy(s[x].name,y);s[x].size=strlen(y);}
#define nmemb 3
struct test
{
      char name[20];
      int size;
}s[nmemb]; 
main()
{
      FILE * stream;
      set_s(0, "Linux!");
      set_s(1, "FreeBSD!");
      set_s(2, "Windows2000.");
      stream=fopen("/tmp/fwrite", "w");
      fwrite(s, sizeof(struct test), nmemb, stream);
      fclose(stream);
}
執行
參考fread()。



 
 

下面是用C++實現二進制文件的讀寫:

本文讀寫文件均使用文件流進行操作,主要使用的類是ifstream, ofstream, 使用時,請務必包含文件fstream。如下:

#include <fstream>

 

寫二進制文件:

 

寫二進制文件應該使用ofstream類,文件的打開模式一定要是 binary,如果傳入的不是 binary, 文件將以ASCII方式打開。

下面是示例代碼,用於寫入文件。

std::ofstream fout("a.dat", std::ios::binary);

int nNum = 20;

std::string str("Hello, world");

fout.write((char*)&nNum, sizeof(int));

fout.write(str.c_str(), sizeof(char) * (str.size()));

fout.close();

而寫文本文件則比較簡單,如下:

std::ofstream fout("b.dat");

int nNum = 20;

std::string str("Hello, world");

fout << nNum << "," << str << std::endl;

fout.close();

 

讀二進制文件:

 

讀取二進制文件可以使用ifstream 類來進行,文件的打開模式一定要是 binary,如果傳入的不是 binary, 文件將以ASCII方式打開。

下面是示例代碼:

std::ifstream fin("a.dat", std::ios::binary);

int nNum;

char szBuf[256] = {0};

fin.read((char*)&nNum, sizeof(int));

fin.read(szBuf, sizeof(char) * 256);

std::cout << "int = " << nNum << std::endl;

std::cout << "str = " << szBuf << std::endl;

fin.close();

而讀取文本文件則比較簡單:

std::ifstream fin("b.dat");

int nNum;

char szBuf[256] = {0};

fin >> nNum >> szBuf;

std::cout << "int = " << nNum << std::endl;

std::cout << "str = " << szBuf << std::endl;

fin.close();

 

文件的打開模式:

 

文件操作時,如果不顯示指定打開模式,文件流類將使用默認值。

在<fstream> 中定義瞭如下打開模式和文件屬性:

ios::app  // 從後面添加

ios::ate  // 打開並找到文件尾

ios::binary  // 二進制模式I/O(與文本模式相對)

ios::in  // 只讀打開

ios::out  // 寫打開

ios::trunc  // 將文件截爲 0 長度

可以使用位操作符 OR 組合這些標誌,比如

ofstream logFile("log.dat", ios::binary | ios::app);

 

二進制文件的複製:

 

這裏我實現了一個二進制文件的複製操作,用於驗證讀寫的正確性,示例代碼如下:

後記

由於文本文件本質上也是磁盤上的一個個二進制編碼,因此,讀寫二進制文件的代碼同樣可以讀寫文本文件,在文件類型不是很明確的讀寫操作中,直接使用二進制讀寫比較可取,如果可以直接判斷文件類型,則可以分別對待。

關於讀取文本文件,請參照http://blog.csdn.net/lightlater/archive/2011/04/15/6326338.aspx


 

 

 

 

發佈了12 篇原創文章 · 獲贊 8 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章