<学习笔记>C语言输入流输出流

一、概念

1.文件输入/输出流类

C++ 提供以下类来执行文件的字符输出和输入:

  • ofstream:输出流写入文件的流类
  • ifstream:输入流从文件中读取的流类
  • fstream:流类以读取和写入文件  

 打开文件

在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream 和 fstream 对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,则使用 ifstream 对象。

open() 函数是 fstream、ifstream 和 ofstream 对象的一个成员。

void open(const char *filename, ios::openmode mode);  //第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。

模式标志描述
ios::app追加模式。所有写入都追加到文件末尾。
ios::ate文件打开后定位到文件末尾。
ios::in打开文件用于读取。
ios::out打开文件用于写入。
ios::trunc如果该文件已经存在,其内容将在打开文件之前被截断,即把文件长度设为 0。

例如,如果您想要以写入模式打开文件,并希望截断文件,以防文件已存在,那么您可以使用下面的语法:

ofstream outfile;

outfile.open("file.dat", ios::out | ios::trunc );
类似地,您如果想要打开一个文件用于读写,可以使用下面的语法:

fstream afile;

afile.open("file.dat", ios::out | ios::in );

(参考https://blog.csdn.net/bestsort/article/details/82858916)

2.ofstream 构造输出流对象

  • ofstream myFile("filename"); 可以在调用默认构造函数之后使用open成员函数打开文件
  • ofstream myFile; //声明一个静态文件输出流对象        

       myFile.open("filename");     //打开文件,使流对象与文件建立联系

  • ofstream myFile("filename", ios_base::out | ios_base::binary);//在构造对象或用open打开文件时可以指定模式//以二进制模式打开文件filename,如文件不存在则创建新文件

       ofstream myFile("filename");等同

 eg:向文件输出
#include <fstream>
using namespace std;
struct Date { 
	int mon, day, year;  
};
int main() {
	Date dt = { 6, 10, 92 };
	ofstream file("date.dat", ios_base::binary);
	file.write(reinterpret_cast<char *>(&dt),sizeof(dt));
    //write函数把内存中的一块内容写到一个文件输出流中
	file.close();
	return 0;
}

3.ifstream 构造输入流对象

  • ifstream myFile("filename"); 可以在调用默认构造函数之后使用open成员函数打开文件
  • ifstream myFile; //声明一个静态文件入出流对象        

       myFile.open("filename");     //打开文件,使流对象与文件建立联系

  • ifstream myFile("filename", ios_base::in | ios_base::binary);//在构造对象或用open打开文件时可以指定模式//以二进制模式打开文件filename,如文件不存在则创建新文件
 eg:从一个payroll文件读一个二进制记录到一个结构中
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

struct SalaryInfo {
	unsigned id;
	double salary;
};

int main() {
	SalaryInfo employee1 = { 600001, 8000 };
	ofstream os("payroll", ios_base::out | ios_base::binary);
	os.write(reinterpret_cast<char *>(&employee1), sizeof(employee1));
	os.close();

	ifstream is("payroll", ios_base::in | ios_base::binary);
	if (is) {
		SalaryInfo employee2;
		is.read(reinterpret_cast<char *>(&employee2), sizeof(employee2));
		cout << employee2.id << " " << employee2.salary << endl;
	} else {
		cout << "ERROR: Cannot open file 'payroll'." << endl;
	}
	is.close();

	return 0;
}

 表1:检查流特定状态

成员函数意义
good()是否发生错误
eof()是否到达文件末尾

 二、例题

11-3 使用I/O流以文本方式建立一个文件test1.txt,写入字符“已成功写入文件!”,用其它字处理程序(例如windows的记事本程序Notepad)打开,看看是否正确写入。 

//法1
#include<fstream>
#include<iostream>
#include<cstring>
using namespace std;
int main(){
	ofstream myfile("test1.txt");
	char c[]="已成功写入文件1";
	myfile.write(c,strlen(c)); 
	myfile.close();
}
//法2
#include<fstream>
#include<iostream>
using namespace std;
int main(){
	ofstream myfile("test1.txt");
    myfile<<"已成功写入文件";
	myfile.close();
}

11-4 使用I/O流以文本方式打开上一题建立的文件test1.txt,读出其内容显示出来,看看是否正确。

#include<fstream>
#include<iostream>
using namespace std;
int main(){
	fstream myfile("test1.txt");//ifstream还是ofstream无所谓
	char ch;
	while(myfile.get(ch))  //这里尝试while(!myfile.eof())还有good()失败了记住这个get
	{
		cout << ch ;
	}
	myfile.close();
}

 11-5 使用I/O流以文本方式打开上题建立的文件test1.txt,在次此文件后面添加字符“已成功添加字符!”,然后读出整个文件的内容显示出来,看看是否正确。

#include<fstream>
#include<iostream>
using namespace std;
int main(){
	fstream myfile1("test1.txt",ios::app);//加 ios::app不然会覆盖重写不是添加 
	myfile1<<"已成功添加字符!"; 
	myfile1.close();
	fstream myfile2("test1.txt");//myfile2改名 后调用 不然不会显示 
	char ch;
	while(myfile2.get(ch))
	{
		cout << ch ;
	}
	myfile2.close();
}

11-6 定义一个dog类,包含体重和年龄两个成员变量及相应的成员函数,声明一个实例dog1,体重为5,年龄为10,使用I/O流把dog1的状态写入磁盘文件,再声明另一个实例dog2,通过读文件把dog1的状态赋给dog2。分别使用文本方式和二进制方式操作文件,看看结果有何不同;再看看磁盘文件的ASCII码有何不同。

解:

以两种方式操作,程序运行结果一样,但磁盘文件的ASCII码不同,使用二进制方式时,磁盘文件的ASCII码为05 00 00 00 0A 00 00 00,使用文本方式时,磁盘文件的ASCII码为05 00 00 00 0D 0A 00 00 00,这是因为此时系统自动把0A转换为了0D 0A

 二进制方式(生成txt中内容乱码)

#include<fstream>
#include<iostream>
using namespace std;
class dog
{
	public:
		dog():age(0),weight(0){
		}
		dog(int a1,int a2):age(a1),weight(a2){
		}
		~dog(){
		}
		int GetWeight()const { return weight; }
        int GetAge() { return age; }
	private:
		int age;
		int weight;
};
int main()
{
	dog dog1(10,5);
	ofstream myfile1("dog1.txt",ios::out|ios::binary);//fstream默认以二进制模式打开文件 txt文档输入内容乱码 
	if (!myfile1)//fstream会unable ofstream就好了 
	{
	cout << "Unable to open for writing.\n";
	return(1);
    }
	myfile1.write((char*) &dog1,sizeof(dog1));//myfile1.write(reinterpret_cast<char*>(&dog1), sizeof(dog1));   
	myfile1.close();
	
	dog dog2;
	ifstream myfile2("dog1.txt",ios::out|ios::binary);//fstream默认以二进制模式打开文件 txt文档输入内容乱码 
	if (!myfile2)//fstream会unable ofstream就好了 
	{
	cout << "Unable to open for writing.\n";
	return(1);
    }
    cout<<dog2.GetAge()<<" "<<dog2.GetWeight() <<endl;
	myfile2.read((char*) &dog2,sizeof(dog2));//从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数
	cout<<dog2.GetAge()<<" "<<dog2.GetWeight() <<endl;
	myfile2.close();
}

 文本方式(生成txt内容正常)

#include <fstream>  
#include <iostream>  
#include <sstream> // For stringstreams  
using namespace std;  
  
class dog {  
public:  
    dog(): age(0), weight(0) {}  
    dog(int a1, int a2): age(a1), weight(a2) {}  
    int GetWeight() const { return weight; }  
    int GetAge() const { return age; }  
  
    // Function to write the dog's state to a stream in text format  
    void WriteToStream(ostream& os) const {  
        os << age << " " << weight;  
    }  
  
    // Function to read the dog's state from a stream in text format  
    void ReadFromStream(istream& is) {  
        is >> age >> weight;  
    }  
  
private:  
    int age;  
    int weight;  
};  
  
int main() {  
    dog dog1(10, 5);  
  
    // Write dog1's state to a text file  
    {  
        ofstream myfile1("dog_text.txt");  
        if (!myfile1.is_open()) {  
            cout << "Unable to open for writing.\n";  
            return 1;  
        }  
        dog1.WriteToStream(myfile1);  
        myfile1.close();  
    }  
  
    dog dog2;  
  
    // Read dog1's state from the text file into dog2  
    {  
        ifstream myfile2("dog_text.txt");  
        if (!myfile2.is_open()) {  
            cout << "Unable to open for reading.\n";  
            return 1;  
        }  
        dog2.ReadFromStream(myfile2);  
        myfile2.close();  
    }  
  
    cout << "dog2's age: " << dog2.GetAge() << ", weight: " << dog2.GetWeight() << endl;  
  
    return 0;  
}

11-7 观察下面的程序,说明每条语句的作用,看看程序执行的结果。 

#include <iostream>
using namespace ::std;

int main()
{
ios_base::fmtflags original_flags = cout.flags(); //1 保存现在的格式化参数设置,以便将来恢复这些设置;
cout<< 812<<'|'<<endl;
cout.setf(ios_base::left,ios_base::adjustfield); //2把对齐方式由缺省的右对齐改为左对齐;
cout.width(10); //3把输出域的宽度由缺省值0改为10;
cout<< 813 << 815 << '\n';
cout.unsetf(ios_base::adjustfield); //4清除对齐方式的设置;
cout.precision(2);
cout.setf(ios_base::uppercase|ios_base::scientific); //5更改浮点数的显示设置;
cout << 831.0 <<endl;

cout.flags(original_flags); //6恢复原来的格式化参数设置。
}

 setiosflags的参数

  • ios_base::skipws 在输入中跳过空白 。
  • ios_base::left 左对齐值,用填充字符填充右边。
  • ios_base::right 右对齐值,用填充字符填充左边(缺省对齐方式)。
  • ios_base::internal 在规定的宽度内,指定前缀符号之后,数值之前,插入指定的填充字符。 ios_base::dec 以十进制形式格式化数值(缺省进制)。
  • ios_base::oct 以八进制形式格式化数值 。
  • ios_base::hex 以十六进制形式格式化数值。
  • ios_base::showbase 插入前缀符号以表明整数的数制。
  • ios_base::showpoint 对浮点数值显示小数点和尾部的0 。
  • ios_base::uppercase 对于十六进制数值显示大写字母A到F,对于科学格式显示大写字母E 。 ios_base::showpos 对于非负数显示正号(“+”)。
  • ios_base::scientific 以科学格式显示浮点数值。
  • ios_base::fixed 以定点格式显示浮点数值(没有指数部分) 。 ios_base::unitbuf 在每次插入之后转储并清除缓冲区内容。 

 11-8 提示用户输入一个十进制整数,分别用十进制、八进制和十六进制形式输出。

#include <iostream>
using namespace std;
int main() {
int n;
cout << "请输入一个十进制整数:";
cin >> n;
cout << "这个数的十进制形式为:" << dec << n << endl;
cout << "这个数的八进制形式为:" << oct << n << endl;
cout << "这个数的十六进制形式为:" << hex << n << endl;
} 

//程序运行输出:
//请输入一个十进制整数:15
//这个数的十进制形式为:15
//这个数的八进制形式为:17
//这个数的十六进制形式为:f

11-9 编写程序实现如下功能:打开指定的一个文本文件,在每一行前加行号。

#include<fstream>  
#include<iostream>  
#include<string>  
using namespace std;  
  
int main() {  
    const char* inputFile = "append.txt";  // 指定要读取的文本文件  
    const char* outputFile = "output.txt"; // 指定输出文件,带行号的文本  
  
    ifstream inFile(inputFile); // 输入文件流  
    ofstream outFile(outputFile); // 输出文件流  
  
    if (!inFile.is_open()) {  
        cerr << "无法打开输入文件:" << inputFile << endl;  
        return 1;  
    }  
  
    if (!outFile.is_open()) {  
        cerr << "无法打开输出文件:" << outputFile << endl;  
        inFile.close();  
        return 1;  
    }  
  
    string line;  
    int lineNumber = 1;  
    while (getline(inFile, line)) { // 逐行读取  
        outFile << lineNumber++ << ". " << line << endl; // 输出行号和内容  
    }  
  
    inFile.close();  
    outFile.close();  
  
    cout << "行号已添加并输出到文件:" << outputFile << endl;  
    return 0;  
}

  • 30
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值