C++;文件流打开模式不明确 < P>在C++中执行文件IO,我们使用OFFROW、IFFSTATE和FSROW类。 ofstream:要在文件上写入的流类 ifstream:从文件读取的流类 fstream:读取和写入文件的流类

C++;文件流打开模式不明确 < P>在C++中执行文件IO,我们使用OFFROW、IFFSTATE和FSROW类。 ofstream:要在文件上写入的流类 ifstream:从文件读取的流类 fstream:读取和写入文件的流类,c++,file-io,stream,C++,File Io,Stream,将文件与流对象关联的过程称为“打开文件”。 打开文件时,我们可以指定打开文件的模式。 我的查询与ios::out和ios:in模式相关 当我创建一个of stream对象并在模式下用ios::打开文件时,我能够 写入文件,但仅在文件已创建时写入(如果文件不存在,还将使用ios::out模式创建文件) 但是,当我创建ifstream对象并使用ios::out模式打开文件时,我能够读取文件 我的问题是,当流的类型(ifstream/)本身指定正在执行的操作类型(输入/输出)时,为什么这些模式(ios

将文件与流对象关联的过程称为“打开文件”。 打开文件时,我们可以指定打开文件的模式。 我的查询与
ios::out
ios:in
模式相关

当我创建一个
of stream
对象并在
模式下用
ios::打开文件时,我能够
写入文件,但仅在文件已创建时写入(如果文件不存在,还将使用
ios::out
模式创建文件)
但是,当我创建
ifstream
对象并使用
ios::out
模式打开文件时,我能够读取文件

我的问题是,当流的类型(
ifstream
/
)本身指定正在执行的操作类型(输入/输出)时,为什么这些模式(
ios::in
/
)由语言提供


还有,为什么这种模棱两可的用法(
of stream
with
ios::in
ifstream
with
ios::out
)在一种情况下有效,而在另一种情况下失败(尽管仅当文件不存在时)

因为模式不限于输入/输出。例如,
ifstream
的构造函数如下所示:

explicit ifstream ( const char * filename, ios_base::openmode mode = ios_base::in );
注意,默认值是
中的ios_base::in,因此您不必自己指定它。但是,
模式
设置的流标志不限于
输入
/
输出
,而是包括:

  • app
    (append)在每次输出操作之前,将流的位置指示器设置为流的末尾
  • ate
    (在末尾)打开时,将流的位置指示器设置为流的末尾
  • 代码>二进制< /代码>(二进制),将流视为二进制而不是文本。
  • 中的
    (输入)允许对流进行输入操作
  • out
    (输出)允许对流执行输出操作
  • trunc
    (truncate)任何当前内容都将被丢弃,假设打开时的长度为零

流的
ifstream
fstream
类都是底层
filebuf
的高级接口,可以通过流的
rdbuf()
成员函数获得这些接口

根据标准,当您使用某种模式打开流的
时,它会像使用
模式| ios_base::out
一样打开下划线流缓冲区。类似地,
ifstream
使用
模式| ios_base::in
fstream
模式
参数逐字传递到下划线流缓冲区

上面的意思是,以下代码使用完全相同的打开标志打开文件:

fstream f("a.txt", ios_base::in | ios_base::out);
ifstream g("a.txt", ios_base::out);
ofstream h("a.txt", ios_base::in);
在这些行之后,您可以使用
f.rdbuf()
g.rdbuf()
h.rdbuf()
执行完全相同的操作,所有这三种操作就像您使用C调用
fopen(“a.txt”、“r+”)
打开文件一样,它提供您读/写访问权限,不会截断文件,如果文件不存在,则会失败

那么,为什么我们有三个不同的班级呢?正如我已经说过的,这些是高级类,在低级流缓冲区上提供高级接口。其思想是,
ifstream
有用于输入的成员函数(如
read()
),
ofstream
有用于输出的成员函数(如
write()
),而
fstream
两者都有。例如,您不能这样做:

g.write("abc", 3); // error: g does not have a write function
但这是可行的,因为尽管
g
是一个
ifstream
,但我们已经用
ios\u base::out
打开了它:

g.rdbuf()->sputn("abc", 3); // we still have write access