c++文件的输入输出与标准输入输出十分相似,首先使用ostream或者fstream打开一个流,将流与文件相关联,然后进行操作。对于一个文件的写入
在程序最后,需要关闭打开的流
这里要注意的是,文件名可以先定义一个string filename,然后用c.str()将其转换成c风格字符串,作为要写入内容的文件名。而在读取文件内容时,这里提供的方法
就是使用while(fin.get(ch))将fin流中的内容读到字符ch中,然后输出。这里我估计get在读到EOF时停止。确切的我忘了- -#。
下面是输出:
之后,认识一下较新的c++才有的函数,is_open()
通常在检查文件流是否打开成功有如下方法:
回到原来的内容,检验文件流是否打开的方法还有
我们通常在初始化文件流的时候并没有加入这些参数是因为我们使用了默认的文件模式,如fin.open("xx.dat")的默认模式是ios_base::in,fout.open("xx.dat")的默认模式是ios_base::out | ios_base::trunc以“ | ”连接两种模式。
ofstream fout; // create an ofstream object named fout
fout.open("jar.txt"); // associate fout with jar.txt
或者
ofstream fout("jar.txt"); // create fout object, associate it with jar.txt
然后
fout<<"something";
对于读取文件内容:
char ch;
fin >> ch; // read a character from the jellyjar.txt file
char buf[80];
fin >> buf; // read a word from the file
fin.getline(buf, 80); // read a line from the file
string line;
getline(fin, line); // read from a file to a string object
因为文件流没有关闭,所以在读取文件时,可以不用指定读取的文件名字,直接读取之前写入流的内容。
在程序最后,需要关闭打开的流
fout.close(); // close output connection to file
fin.close(); // close input connection to file
下面是例子:
Listing 17.16 fileio.cpp
// fileio.cpp -- saving to a file
#include <iostream> // not needed for many systems
#include <fstream>
#include <string>
int main()
{
using namespace std;
char ch;
// show initial contents
ifstream fin;
fin.open(file);
if (fin.is_open())
{
cout << "Here are the current contents of the "
<< file << " file:\n";
while (fin.get(ch))
cout << ch;
fin.close();
}
// add new names
ofstream fout(file, ios::out | ios::app);
if (!fout.is_open())
{
cerr << "Can't open " << file << " file for output.\n";
exit(EXIT_FAILURE);
}
cout << "Enter guest names (enter a blank line to quit):\n";
string name;
while (getline(cin,name) && name.size() >0)
{
fout << name << endl;
}
fout.close();
// show revised file
fin.clear(); // not necessary for some compilers
fin.open(file);
if (fin.is_open())
{
cout << "Here are the new contents of the "
<< file << " file:\n";
while (fin.get(ch))
cout << ch;
fin.close();
}
cout << "Done.\n";
return 0;
}
这里要注意的是,文件名可以先定义一个string filename,然后用c.str()将其转换成c风格字符串,作为要写入内容的文件名。而在读取文件内容时,这里提供的方法
就是使用while(fin.get(ch))将fin流中的内容读到字符ch中,然后输出。这里我估计get在读到EOF时停止。确切的我忘了- -#。
下面是输出:
Enter name for new file: pythag
Enter your secret number: 3.14159
Here are the contents of pythag:
For your eyes only!
Your secret number is 3.14159
Done
这个是书本的,我没去重复。
之后,认识一下较新的c++才有的函数,is_open()
通常在检查文件流是否打开成功有如下方法:
fin.open(argv[file]);
if (fin.fail()) // open attempt failed
{
...
}
这里的argv是main函数的参数,因为对于一般的main函数,为
int main(int argc, char *argv[])
argc是可执行程序的参数个数,argv是一个数组,0 1 2代表参数位置,例如:
wc report1 report2 report3
wc是可执行程序,report1 2 3是它的参数。这里argc = 4,argv[0]是wc依次类推。
回到原来的内容,检验文件流是否打开的方法还有
if(fin.fail()) ... // failed to open
if(!fin.good()) ... // failed to open
if (!fin) ... // failed to open
但是其中就有一个问题,当文件打不开时,它返回的只有一种提示,而对于is_open(),能够对于以不合适的模式打开文件的错误进行提示。
对于输入输出的模式问题,可以有如下的表示方法:
ifstream fin("banjo", mode1); // constructor with mode argument
ofstream fout();
fout.open("harp", mode2); // open() with mode arguments
mode的种类有:
常量 | 含义 |
ios_base::in | 打开文件,以便读取 |
ios_base::out | 打开文件,以便写入 |
ios_base::ate | 打开文件,并移至末尾 |
ios_base::app | 追加至末尾处添加 |
ios_base::trunc | 如果文件存在,删除以前内容 |
ios_base::binary | 二级制文件 |
我们通常在初始化文件流的时候并没有加入这些参数是因为我们使用了默认的文件模式,如fin.open("xx.dat")的默认模式是ios_base::in,fout.open("xx.dat")的默认模式是ios_base::out | ios_base::trunc以“ | ”连接两种模式。
注意:ate和app都是将内容添加到文件末尾,但是他们的区别是,app只是将数据放到文件末尾,而ate则是把指针指向文件末尾。
以下例子:
1.追加文件
Listing 17.18 append.cpp
// append.cpp -- appending information to a file
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // (for exit()
const char * file = "guests.txt";
int main()
{
using namespace std;
char ch;
// show initial contents
ifstream fin;
fin.open(file);
if (fin.is_open())
{
cout << "Here are the current contents of the "
<< file << " file:\n";
while (fin.get(ch))
cout << ch;
fin.close();
}
// add new names
ofstream fout(file, ios::out | ios::app);
if (!fout.is_open())
{
cerr << "Can't open " << file << " file for output.\n";
exit(EXIT_FAILURE);
}
cout << "Enter guest names (enter a blank line to quit):\n";
string name;
while (getline(cin,name) && name.size() >0)
{
fout << name << endl;
}
fout.close(); // show revised file
fin.clear();
// not necessary for some compilers
fin.open(file);
if (fin.is_open())
{
cout << "Here are the new contents of the "
<< file << " file:\n";
while (fin.get(ch))
cout << ch;
fin.close();
}
cout << "Done.\n";
return 0;
}
输入输出:
Enter guest names (enter a blank line to quit):
Genghis Kant
Hank Attila
Charles Bigg
Here are the new contents of the guests.txt file:
Genghis Kant
Hank Attila
Charles Bigg
Done.
第一次运行是文件还没有创建,此时没有读取操作,第二次运行时,将先预览guest.txt文件,然后将添加的名字加入到文件末尾。
Here are the current contents of the guests.txt file:
Genghis Kant
Hank Attila
Charles Bigg
Enter guest names (enter a blank line to quit):
Greta Greppo
LaDonna Mobile
Fannie Mae
Here are the new contents of the guests.txt file:
Ghengis Kant
Hank Attila
Charles Bigg
Greta Greppo
LaDonna Mobile
Fannie Mae
Done.
下面是另外一个例子:
// binary.cpp -- binary file I/O
#include <iostream> // not required by most systems
#include <fstream>
#include <iomanip>
#include <cstdlib> // for exit()
inline void eatline() { while (std::cin.get() != '\n') continue; }
struct planet
{
char name[20]; // name of planet
double population; // its population
double g; // its acceleration of gravity
};
const char * file = "planets.dat";
int main()
{
using namespace std;
planet pl;
cout << fixed << right;
// show initial contents
ifstream fin;
fin.open(file, ios_base::in |ios_base::binary); // binary file
//NOTE: some systems don't accept the ios_base::binary mode
if (fin.is_open())
{
cout << "Here are the current contents of the "
<< file << " file:\n";
while (fin.read((char *) &pl, sizeof pl))
{
cout << setw(20) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
}
fin.close();
}
// add new data
ofstream fout(file,ios_base::out | ios_base::app | ios_base::binary);
//NOTE: some systems don't accept the ios::binary mode
if (!fout.is_open())
{
cerr << "Can't open " << file << " file for output:\n";
exit(EXIT_FAILURE);
}
cout << "Enter planet name (enter a blank line to quit):\n";
cin.get(pl.name, 20);
while (pl.name[0] != '\0')
{
eatline();
cout << "Enter planetary population: ";
cin >> pl.population;
cout << "Enter planet's accelerationof gravity: ";
cin >> pl.g;
eatline();
fout.write((char *) &pl, sizeof pl);
cout << "Enter planet name (enter a blank line "
"to quit):\n";
cin.get(pl.name, 20);
}
fout.close();
// show revised file
fin.clear(); // not required for some implementations, but won't hurt
fin.open(file, ios_base::in | ios_base::binary);
if (fin.is_open())
{
cout << "Here are the new contents of the "
<< file << " file:\n";
while (fin.read((char *) &pl, sizeof pl))
{
cout << setw(20) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
}
fin.close();
}
cout << "Done.\n";
return 0;
}