C++でファイルを読み書きする方法

青灯夜游
リリース: 2023-01-07 11:41:08
オリジナル
24659 人が閲覧しました

c ファイルの読み取りと書き込みのメソッド: 1. 「>>」および「<<」演算子を使用します。 2. 「istream::read()」および「ostream::write」を使用します。 ()" メソッド; 3. "istream::get()" および "ostream::put()" メンバー メソッドを使用します。

C++でファイルを読み書きする方法

このチュートリアルの動作環境: Windows 7 システム、C 17 バージョン、Dell G3 コンピューター。

方法 1: C >> および << テキスト ファイルの読み取りと書き込み

fstream または ifstream クラスは、ファイル読み取りを実装すると、これらはすべて >> 出力ストリーム演算子を内部的にオーバーロードします。同様に、fstream クラスと ofstream クラスはファイルの書き込みを担当し、内部的にも <code>&lt ;< 出力ストリーム演算子がオーバーロードされています。

したがって、fstream または ifstream クラス オブジェクトがファイルを開くとき (通常、開くモードとして ios::in を使用します)、>> 入力ストリーム演算子を直接使用して、ファイルに格納されている文字を読み取ることができます。 file (または string); fstream または ofstream クラス オブジェクトがファイルを開くとき (通常、開くモードとして ios::out を使用します)、<< 出力ストリーム演算子を直接使用して文字 (または文字列) をファイルに書き込むことができます。ファイル。

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    int x,sum=0;
    ifstream srcFile("in.txt", ios::in); //以文本模式打开in.txt备读
    if (!srcFile) { //打开失败
        cout << "error opening source file." << endl;
        return 0;
    }
    ofstream destFile("out.txt", ios::out); //以文本模式打开out.txt备写
    if (!destFile) {
        srcFile.close(); //程序结束前不能忘记关闭以前打开过的文件
        cout << "error opening destination file." << endl;
        return 0;
    }
    //可以像用cin那样用ifstream对象
    while (srcFile >> x) {
        sum += x;
        //可以像 cout 那样使用 ofstream 对象
        destFile << x << " ";
    }
    cout << "sum:" << sum << endl;
    destFile.close();
    srcFile.close();
    return 0;
}
ログイン後にコピー

このプログラムを実行する前に、プログラム ソース ファイルと同じディレクトリに in.txt ファイルを手動で作成する必要があります。内部に保存されている文字列は次のとおりであると仮定します:

10 20 30 40 50
ログイン後にコピー

作成後、実行しますプログラムの実行結果:

sum:150
ログイン後にコピー

同時に、in.txt ファイルと同じディレクトリに out.txt ファイルが生成されます。このファイルに格納されている文字は、in.txt ファイルとまったく同じです。 in.txt ファイル。読者は自分でファイルを開くことができます。確認してください。

プログラムの実行結果を解析すれば理解するのは難しくありませんが、in.txtファイル内の「10 20 30 40 50」という文字列に対して、srcFileオブジェクトは「10」、「20」を順番に変換していきます。 "、"30"、"40"、"50" を読み出し、int 型の整数 10、20、30、40、50 に解析して x に代入し、同時に sum との加算演算も完了します。

同様に、in.txt ファイルから読み取られて解析された各整数 x について、destFile オブジェクトはそれを対応する文字列に変更せずに解析し (整数 10 を文字列 " 10" に解析するなど)、これを「」スペース文字とともに out.txt ファイルに書き込みます。

方法 2: C read() および write() によるバイナリ ファイルの読み取りおよび書き込み

C ostream::write( ) メソッド Write files

ofstream および fstream の write() メンバー メソッドは、実際には ostream クラスから継承されており、その機能は、メモリ内のバッファーが指す count バイトをファイルに書き込むことです。

ostream & write(char* buffer, int count);
ログイン後にコピー

このうち、buffer はファイルに書き込むバイナリデータの開始位置を指定するのに使用し、count は書き込むバイト数を指定するのに使用します。

つまり、このメソッドは ostream クラスの cout オブジェクトによって呼び出すことができ、画面に文字列を出力するためによく使用されます。同時に、ofstream オブジェクトまたは fstream オブジェクトによって呼び出されて、指定された数のバイナリ データをファイルに書き込むこともできます。

同時に、このメソッドは、関数に作用する参照の形式でオブジェクトを返します。たとえば、obj.write() メソッドの戻り値は、obj オブジェクトへの参照です。

注意すべき点は、write() メンバー メソッドはファイルに多数のバイトを書き込みますが、write() 関数を呼び出すときに、これらのバイトがファイル内で書き込まれる特定の場所が指定されていないことです。 。実際、write() メソッドは、ファイル書き込みポインタが指す場所からバイナリ データを書き込みます。いわゆるファイル書き込みポインタは、ofstream または fstream オブジェクトによって内部的に維持される変数です。ファイルが最初に開かれたとき、ファイル書き込みポインタはファイルの先頭を指します (ios::app モードで開かれた場合は、ファイル書き込みポインタはファイルの先頭を指します) write() メソッドを使用すると、n バイトの書き込みが行われ、書き込みポインタの指す位置が n バイトだけ後方に移動します。

次のプログラムは、学生情報をバイナリ形式でファイルに書き込む方法を示しています。

#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
public:
    char szName[20];
    int age;
};
int main()
{
    CStudent s;
    ofstream outFile("students.dat", ios::out | ios::binary);
    while (cin >> s.szName >> s.age)
        outFile.write((char*)&s, sizeof(s));
    outFile.close();
    return 0;
}
ログイン後にコピー

入力:

Tom 60↙
Jack 80↙
Jane 40↙
^Z↙
ログイン後にコピー

このうち、 は、出力改行記号 #^Z は、Ctrl Z キーの組み合わせを入力して入力を終了することを意味します。

プログラムを実行すると、72バイトのデータを含むstudents.datファイルが自動的に生成されますが、このファイルを「メモ帳」で開くと、次のような文字化けが発生する場合があります:

Tom 烫烫烫烫烫烫烫烫<   Jack 烫烫烫烫烫烫烫蘌   Jane 烫烫烫烫烫烫烫?
ログイン後にコピー

プログラムの 13 行目で指定されているファイルのオープン モードは ios::out | ios::binary、つまりバイナリ書き込みモードで開かれることに注意してください。 Windows プラットフォームでは、ファイルをバイナリ モードで開くことが非常に重要です。そうしないと、エラーが発生する可能性があります。

また、15 行目では s オブジェクトをファイルに書き込みます。 s のアドレスはファイルに書き込まれるメモリ バッファのアドレスですが、&s は char * 型ではないため、強制的な型変換が必要です。16 行目、ファイルは使用後に閉じる必要があり、そうでない場合は、プログラム終了後、ファイルが不完全になる可能性があります。

C istream::read() メソッドはファイルを読み取ります

ifstream と fstream の read() メソッドは実際には istream クラスから継承しており、その関数はまさにwrite() と同じ 逆の方法は、ファイルから count バイトのデータを読み取ることです。このメソッドの構文形式は次のとおりです:

istream & read(char* buffer, int count);
ログイン後にコピー

其中,buffer 用于指定读取字节的起始位置,count 指定读取字节的个数。同样,该方法也会返回一个调用该方法的对象的引用。

和 write() 方法类似,read() 方法从文件读指针指向的位置开始读取若干字节。所谓文件读指针,可以理解为是 ifstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件读指针指向文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 read() 方法读取 n 个字节,读指针指向的位置就向后移动 n 个字节。因此,打开一个文件后连续调用 read() 方法,就能将整个文件的内容读取出来。

通过执行 write() 方法的示例程序,我们将 3 个学生的信息存储到了 students.dat 文件中,下面程序演示了如何使用 read() 方法将它们读取出来:

#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
public:
    char szName[20];
    int age;
};
int main()
{
    CStudent s;       
    ifstream inFile("students.dat",ios::in|ios::binary); //二进制读方式打开
    if(!inFile) {
        cout << "error" <<endl;
        return 0;
    }
    while(inFile.read((char *)&s, sizeof(s))) { //一直读到文件结束
        cout << s.szName << " " << s.age << endl;   
    }
    inFile.close();
    return 0;
}
ログイン後にコピー

程序的输出结果是:

Tom 60
Jack 80
Jane 40
ログイン後にコピー

注意,程序中第 18 行直接将 read() 方法作为 while 循环的判断条件,这意味着,read() 方法会一直读取到文件的末尾,将所有字节全部读取完毕,while 循环才会终止。

方法3:C++ get()和put()读写文件

在某些特殊的场景中,我们可能需要逐个读取文件中存储的字符,或者逐个将字符存储到文件中。这种情况下,就可以调用 get() 和 put() 成员方法实现。

C++ ostream::put()成员方法

我们知道,fstream 和 ofstream 类继承自 ostream 类,因此 fstream 和 ofstream 类对象都可以调用 put() 方法。

当 fstream 和 ofstream 文件流对象调用 put() 方法时,该方法的功能就变成了向指定文件中写入单个字符。put() 方法的语法格式如下:

ostream& put (char c);
ログイン後にコピー

其中,c 用于指定要写入文件的字符。该方法会返回一个调用该方法的对象的引用形式。例如,obj.put() 方法会返回 obj 这个对象的引用。

举个例子:

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    char c;
    //以二进制形式打开文件
    ofstream outFile("out.txt", ios::out | ios::binary);
    if (!outFile) {
        cout << "error" << endl;
        return 0;
    }
    while (cin >> c) {
        //将字符 c 写入 out.txt 文件
        outFile.put(c);
    }
    outFile.close();
    return 0;
}
ログイン後にコピー

执行程序,输入:

https://www.php.cn/↙
^Z↙
ログイン後にコピー

其中,表示输入换行符;^ZCtrl+Z 的组合键,表示输入结束。

由此,程序中通过执行 while 循环,会将 "https://www.php.cn/" 字符串的字符逐个复制给变量 c,并逐个写入到 out.txt 文件。

注意,由于文件存放在硬盘中,硬盘的访问速度远远低于内存。如果每次写一个字节都要访问硬盘,那么文件的读写速度就会慢得不可忍受。因此,操作系统在接收到 put() 方法写文件的请求时,会先将指定字符存储在一块指定的内存空间中(称为文件流输出缓冲区),等刷新该缓冲区(缓冲区满、关闭文件、手动调用 flush() 方法等,都会导致缓冲区刷新)时,才会将缓冲区中存储的所有字符“一股脑儿”全写入文件。

C++ istream::get()成员方法

和 put() 成员方法的功能相对的是 get() 方法,其定义在 istream 类中,借助 cin.get() 可以读取用户输入的字符。在此基础上,fstream 和 ifstream 类继承自 istream 类,因此 fstream 和 ifstream 类的对象也能调用 get() 方法。

当 fstream 和 ifstream 文件流对象调用 get() 方法时,其功能就变成了从指定文件中读取单个字符(还可以读取指定长度的字符串)。值得一提的是,get() 方法的语法格式有很多(请猛击这里了解详情),这里仅介绍最常用的 2 种:

int get();
istream& get (char& c);
ログイン後にコピー

其中,第一种语法格式的返回值就是读取到的字符,只不过返回的是它的 ASCII 码,如果碰到输入的末尾,则返回值为 EOF。第二种语法格式需要传递一个字符变量,get() 方法会自行将读取到的字符赋值给这个变量。

本节前面在讲解 put() 方法时,生成了一个 out.txt 文件,下面的样例演示了如何通过 get() 方法逐个读取 out.txt 文件中的字符:

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    char c;
    //以二进制形式打开文件
    ifstream inFile("out.txt", ios::out | ios::binary);
    if (!inFile) {
        cout << "error" << endl;
        return 0;
    }
    while ( (c=inFile.get())&&c!=EOF )   //或者 while(inFile.get(c)),对应第二种语法格式
    {
        cout << c ;
    }
    inFile.close();
    return 0;
}
ログイン後にコピー

程序执行结果为:

https://www.php.cn/
ログイン後にコピー

注意,和 put() 方法一样,操作系统在接收到 get() 方法的请求后,哪怕只读取一个字符,也会一次性从文件中将很多数据(通常至少是 512 个字节,因为硬盘的一个扇区是 512 B)读到一块内存空间中(可称为文件流输入缓冲区),这样当读取下一个字符时,就不需要再访问硬盘中的文件,直接从该缓冲区中读取即可。

更多编程相关知识,请访问:编程视频!!

以上がC++でファイルを読み書きする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート