文件的讀寫、二進制文件的讀寫、文件隨機讀寫

1、文件的讀寫linux

前面所提,流的讀寫主要有<<, >>, get, put, read, write 等操做,ofstream 繼承自ostream, ifstream 繼承自 istream,故操做函數都是一致的。ios

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;

int main(void)
{
    ofstream fout("test.txt");
    fout << "abc" << " " << 200;
    fout.close();

    ifstream fin("test.txt");
    string s;
    int n;
    //fin>>n>>s;
    fin >> s >> n;
    cout << s << " " << n << endl;

    ofstream fout1("test2.txt");
    assert(fout1);
    char ch;

    for (int i = 0; i < 26; i++)
    {
        ch = 'A' + i;
        fout1.put(ch);
    }
    fout1.close();

    ifstream fin1("test2.txt");
    while (fin1.get(ch))
    {
        cout << ch;
    }
    cout << endl;


    return 0;
}

 

2、二進制文件的讀寫編程

二進制文件不一樣於文本文件,它可用於任何類型的文件(包括文本文件)
對二進制文件的讀寫可採用從istream類繼承下來的成員函數read()和從ostream類繼承下來的成員函數write()
文件打開操做時使用枚舉常量ios::binary,例如:ofstream fout(「binary.dat」,ios::out | ios::binary);
app

(一)、write成員 函數編輯器

函數功能:以字節爲單位向文件流中寫入整塊數據,最有價值的應用能夠處理結構體變量和類對象
函數原型:
函數

ostream& write( const char* pch, int nCount );spa

函數參數:
pch 寫入的數據的指針
nCount 寫入數據的字節大小
.net


(二)、read 成員 函數
指針

函數功能:從文件流中讀出整塊數據
函數原型:
對象

istream& read( char* pch, int nCount ); 

函數參數:
pch 用來接收數據的指針
nCount 讀取的字節數的大小

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
#include <cassert>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct Test
{
    int a;
    int b;
};

int main(void)
{
    ofstream fout("test3.txt", ios::out | ios::binary); // 二進制方式打開,'\n'不作轉換
    fout << "ABC\n"; // << 是以文本方式寫入
    fout.close();

    Test test = { 100, 200 };
    ofstream fout1("test4.txt", ios::out | ios::binary);
    fout1.write(reinterpret_cast<char *>(&test), sizeof(Test));
    // 二進制方式寫入後用文本編輯器打開test4.txt 亂碼
    fout1.close();

    Test test2;
    ifstream fin("test4.txt", ios::in | ios::binary);
    fin.read(reinterpret_cast<char *>(&test2), sizeof(Test));
    cout << test2.a << " " << test2.b << endl;

    ofstream fout2("test5.txt", ios::out | ios::binary);
    fout2 << "abc" << 200; // << 是以文本方式寫入
    fcout2.close();

    return 0;
}

在window下以文本方式打開文件,則以文本方式寫入時遇到'\n' , 轉換爲'\r\n',以二進制方式打開則不作轉換,故test3.txt 文件大小爲4個字節。

而寫入100(write 是以二進制方式寫入)就再也不是寫入'1', '0' ,' 0' 的ascii 碼,而是按照內存原本二進制形式寫入,故用文本編輯器打開test4.txt 時會出

現亂碼。文件大小爲8個字節(兩個int)。同理,test5.txt 雖然以二進制打開,可是以文本方式(<< 是以文本方式寫入)寫入的,故寫入200後用文本

編輯器打開不會出現亂碼,文件大小爲6個字節。

有關文本文件與二進制文件的區別,請參考這裏


使用read, write 讀取string 的時候須要注意,string 實際上內部是一些指針成員,sizeof(string)=32 (跟編譯器實現有關),即string 大小是必定的,

它的指針成員保存的字符串長度不必定是32,故咱們應該這些讀寫:

 C++ Code 
1
2
3
4
5
6
7
8
9
 
string str1 =  "fdsfafsdsf";
int len = str1.length();
ofstream fout("test6.txt", ios::out | ios::binary);
fout.write(str1.data(), str1.length());

string str2;
str2.resize(len);
ifstream fin("test6.txt", ios::in | ios::binary);
fin.read(&str2[0], len);

若是像這樣寫入  fout.write((char*)&str1, sizeof(str1)); 必定是錯誤的,由於寫入的是str1 的指針成員,而不是指針成員指向的字符串,並且str1 的大小恆等於32。


3、文件隨機讀寫

(一)、當前文件流活動指針

文件流指針用以跟蹤發生 I/O 操做的位置
每當從流中讀取或寫入一個字符,當前活動指針就會向前移動
當打開方式中不含有ios::ate或ios::app選項時,則文件指針被自動移到文件的開始位置,即字節地址爲0的位置。


(二)、文件的隨機讀寫 seekp和seekg

seekp 和 seekg 相似與C庫的fseek, linux系統調用的lseek。

函數功能

seekp:設置輸出文件流的文件流指針位置

seekg:設置輸入文件流的文件流指針位置

函數原型:

ostream& seekp( streampos pos );

ostream& seekp( streamoff off, ios::seek_dir dir );

istream& seekg( streampos pos );

istream& seekg( streamoff off, ios::seek_dir dir );

函數參數

pos:新的文件流指針位置值

off:須要偏移的值

dir:搜索的起始位置

dir參數用於對文件流指針的定位操做上,表明搜索的起始位置
在ios中定義的枚舉類型:

enum seek_dir {beg, cur, end};

每一個枚舉常量的含義:
ios::beg:文件流的起始位置
ios::cur:文件流的當前位置
ios::end:文件流的結束位置

tellp 和 tellg 相似C庫的ftell,,linux 系統調用的lseek(fd, 0, SEEK_CUR);

函數功能

tellp:得到輸出的文件流指針的當前位置,以字節爲單位

tellg:得到輸入的文件流指針的當前位置,以字節爲單位

函數原型:

streampos tellp();

streampos tellg();

函數返回值:其實是一個long類型

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
#include <cassert>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;


int main(void)
{
    ifstream fin("test7.txt");
    assert(fin);
    fin.seekg(2);//位置從0開始計數

    char ch;
    fin.get(ch);
    cout << ch << endl;

    fin.seekg(-1, ios::end); //end 其實是EOF位置
    fin.get(ch);
    cout << ch << endl;

    fin.seekg(0, ios::end);
    streampos pos = fin.tellg();
    cout << pos << endl;

    return 0;
}

假設test7.txt 如今存放abcdefg 7個字符,則輸出爲c g 7 .

 

參考:

C++ primer 第四版 Effective C++ 3rd C++編程規範

相關文章
相關標籤/搜索