C++ 文件输入输出(三)

///假如你打算设置不止一个的打开模式标志,只须使用OR操作符或者是 | ,像这样:

///ios::ate | ios::binary

///fstream File(“cpp-home.txt”,ios::in | ios::out);

///实际上,这只是一个声明语句。我将在下面数行之后给你一个代码示例。但此时我首先想提及一些你应当
///知道的内容。
///上面的代码创建了一个名为“File”的流式文件的句柄。如你所知,它是fstream类的一个对象。当使用
///fstream时,你应当指定ios::in和ios::out作为文件的打开模式。这样,你就可以同时对文件进行
///读、写,而无须创建新的文件句柄。噢,当然,你也可以只进行读或者写的操作。那样的话,相应地你应当
///只使用ios::in或者只使用ios::out —— 要思考的问题是:如果你打算这么做,为什么你不分别用ifstream
///及ofstream来实现呢?
///********************************************************************************************
///示例代码:这个test 得手动创建
/*
#include <fstream>
#include<iostream>
using namespace std;
int main()
{
    fstream File("test.txt",ios::in | ios::out);

    File << "Hi!"; //将“Hi!”写入文件
    static char str[10]; //当使用static时,数组会自动被初始化
               //即是被清空为零


    File.seekg(ios::beg); // 回到文件首部
                  // 此函数将在后面解释
    File >> str;
    cout << str << endl;

    File.close();
    return 0;
}
*/
///fstream File(“test.txt”, ios::in | ios::out); —— 此行创建一个fstream对象,
///执行时将会以读/写方式打开test.txt文件。这意味着你可以同时读取文件并写入数据。
 
///File << “Hi!”; —— 我打赌你已经知道它的意思了。
 
///static char str[10]; —— 这将创建一个容量为10的字符数组。我猜static对你而言或者有些陌生,
///如果这样就忽略它。这只不过会在创建数组的同时对其进行初始化。
 
///File.seekg(ios::beg); —— OK,我要让你明白它究竟会做些什么,因此我将以一些有点儿离题、
///但挺重要的内容开始我的解释。
///还记得它么:
/*
while(!OpenFile.eof())
    {
       OpenFile.get(ch);
       cout << ch;
    }
 */
///你是不是曾经很想知道那背后真正执行了什么操作?不管是或不是,我都将为你解释。这是一个
///while
///型循环,它会一直反复,直至程序的操作到达文件的尾端。但这个循环如何知道是否已经到了文件
///末尾?嗯,当你读文件的时候,会有一个类似于“内置指针(inside-pointer)”的东西,它表明你读取
///(写入也一样)已经到了文件的哪个位置,就像记事本中的光标。而每当你调用OpenFile.get(ch)的时
///候,它会返回当前位置的字符,存储在ch变量中,并将这一内置指针向前移动一个字符。因此下次该函数
///再被调用时,它将会返回下一个字符。而这一过程将不断反复,直到读取到达文件尾。所以,
///让我们回到那行代码:函数seekg()将把内置指针定位到指定的位置(依你决定)。你可以使用:
 
///ios::beg —— 可将它移动到文件首端
///ios::end —— 可将它移动到文件末端
 
///或者,你可以设定向前或向后跳转的字符数。例如,如果你要向定位到当前位置的5个字符以前,
///你应当写:
///File.seekg(-5);
///如果你想向后跳过40个字符,则应当写:
///File.seekg(40);
///同时,我必须指出,函数seekg()是被重载的,它也可以带两个参数。另一个版本是这样子的:
///File.seekg(-5,ios::end);
///在这个例子中,你将能够读到文件文本的最后4个字符,因为:
///1)你先到达了末尾(ios::end)
///2)你接着到达了末尾的前五个字符的位置(-5)
///*******************************************************************************************
///为什么你会读到4个字符而不是5个?噢,只须把最后一个看成是“丢掉了”,因为文件最末端的“
///东西”既不是字符也不是空白符,那只是一个位置(译注:或许ios::end所“指”的根本已经超出了
///文件本身的范围,确切的说它是指向文件最后一个字符的下一个位置,有点类似STL中的各个容器
///的end迭代点是指向最后一个元素的*下一位置*。这样设计可能是便于在循环中实现遍历)。
///你现在可能想知道为什么我要使用到这个函数。呃,当我把“Hi”写进文件之后,内置指针将被设
///为指向其后面……也就是文件的末尾。因此我必须将内置指针设回文件起始处。这就是这个函数在
///此处的确切用途。
///File >> str; 这也是新鲜的玩意儿,我确信这行代码让你想起了cin >> .实际上,它们之间有着
///相当的关联。此行会从文件中读取一个单词,然后将它存入指定的数组变量中。
///例如,如果文件中有这样的文本片断:
///Hi! Do you know me?
///使用File >> str,则只会将“Hi!”输出到str数组中。你应当已经注意到了,它实际上是将空格作为
///单词的分隔符进行读取的。
///由于我存入文件中的只是单独一个“Hi!”,我不需要写一个while循环,那会花费更多的时间来写
///代码。这就是我使用此方法的原因。顺便说一下,到目前为止,我所使用的读取文件的while循环
///中,程序读文件的方式是一个字符一个字符进行读取的。然而你也可以一个单词一个单词地进行
///读取,像这样:
/*
char str[30]; //每个单词的长度不能超过30个字符
while(!OpenFile.eof())
    {
       OpenFile >> str;
       cout << str;
    }
*/
///你也可以一行一行地进行读取,像这样:
/*
char line[100]; //每个整行将会陆续被存储在这里
while(!OpenFile.eof())
{
OpenFile.getline(line,100); // 100是数组的大小
cout << line << endl;
}
*/
///你现在可能想知道应当使用哪种方法。嗯,我建议你使用逐行读取的方式,或者是最初我提及的
///逐字符读取的方式。而逐词读取的方式并非一个好的方案,因为它不会读出新起一行这样的信息,
///所以如果你的文件中新起一行时,它将不会将那些内容新起一行进行显示,而是加在已经打印的
///文本后面。而使用getline()或者get()都将会向你展现出文件的本来面目!
///现在,我将向你介绍如何检测文件打开操作是否成功。实现上,好的方法少之又少,我将都会涉
///及它们。需要注意的是,出现“X”的时候,它实际可以以“o”、 “i”来代替,或者也可以什么都不
///是(那将是一个fstream对象)。
///通常做法:
/*
Xfstream File(“love.txt”);
if (!File)
{
cout << “Error opening the file! Aborting…/n”;
exit(1);
}
*/
///如果文件已经被创建,返回一个错误
/*
ofstream File("unexisting.txt", ios::nocreate);
 
if(!File)
{
cout << “Error opening the file! Aborting…/n”;
exit(1);
}
*/
///使用fail()函数
/*
ofstream File("filer.txt", ios::nocreate);
 
if(File.fail())
{
cout << “Error opening the file! Aborting…/n”;
exit(1);
}
*/
///fail()函数。如果有任何输入/输出错误(不是在文件末尾)发生,它将返回非零值。
///例如,如果你已经创建一个流文件对象,但你没有进行打开文件操作,像这样:
 
///ifstream File; //也可以是一个ofstream
 
///这样,我们就拥有一个文件句柄,但我们仍然没有打开文件。如果你打算迟些打开它,那么
///可以用open()函数来实现,我已经在本教程中将它介绍了。但如果在你的程序的某处,你可能需要
///知道当前的句柄是否关联了一个已经打开的文件,那么你可以用is_open()来进行检测。
///如果文件没有打开,它将返回0 (false);如果文件已经打开,它将返回1 (true)。例如:
/* 
ofstream File1;
File1.open("file1.txt");
cout << File1.is_open() << endl;
*/

///上面的代码将会返回1(译注:指File1.is_open()函数,下句同),因为我们已经打开了一个文件
///(在第二行)。而下面的代码则会返回0,这是由于我们没有打开文件,而只是创建了一个流文件
///句柄:
/*
ofstream File1;
cout << File1.is_open() << endl;
*/
点头点头 单曲*无限*循环中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值