stl的std::ofstream怎么判断文件的类型??

trancebaby 2003-07-14 04:48:15
具体地说,有一个函数:
void AppendFileTo(std::ofstream &outFile,AnsiString sAppendFileName)
要根据outFile的类型进行操作,要怎么才能知道是不是std::ios_base::binary呢?
因为我要根据是不是文本文件进行处理。

谢谢~
...全文
259 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
trancebaby 2003-07-15
  • 打赏
  • 举报
回复
to wintersun(长虹):
谢谢你的解答,不过这种用法确实感觉不太好,我来自己试一试吧。
我为了找这个问题的答案,想去找fstream的源代码(主要想知道void open(const char *s, ios_base::openmode mode = ios_base::in);这个函数的mode传进去做了什么事情),但是下载了几个stl的源代码,都不含fstream,不知为什么。

to ccom(ccom):
照理来说,std::ofstream &outFile在open以后就应该知道是不是binary了。所以我想应该有办法知道吧。

stl的文档查起来真麻烦,因为有很多继承的层次,我不知道我需要的函数在哪一层有提供。
Kidsheep 2003-07-15
  • 打赏
  • 举报
回复
Streams库不是包括在STL中哦,它没有模板的。

不过你发现的这个现象还是蛮有价值的
trancebaby 2003-07-15
  • 打赏
  • 举报
回复
谢谢解答。准备给分。
我为什么看到
extern _CRTIMP FILE *__cdecl __Fiopen(const char *,ios_base::openmode);
以后就找不到__Fiopen的程序体了呢?你是直接在VC的Debug方式下跑的吧?

那么这样我还是做针对于文本和binary的两个AppendFileTo函数吧。
wintersun 2003-07-15
  • 打赏
  • 举报
回复

我简单分析了一下VC 6.0中fstream的STL源码:

typedef basic_ofstream<char, char_traits<char> > ofstream;

类basic_ofstream的继承关系为:basic_ofstream-->basic_ostream-->basic_ios

对照实例:ofstream outfile("pq.txt",ios_base::binary | ios_base::app);
跟踪整个继承体系对explict construction的处理.

explicit basic_ofstream(const char *_S,
ios_base::openmode _M = out | trunc)
: basic_ostream<_E, _Tr>(&_Fb)
{if (_Fb.open(_S, _M | out) == 0)
setstate(failbit);
}
/*在这个构造函数里:
_S---"pq.txt"
_M--ios_base::binary | ios_base::app
打开模式_M只有一个流向,即_Fb.open
*/


_Myt *open(const char *_S, ios_base::openmode _M)
{_Filet *_Fp;
if (_File != 0 || (_Fp = __Fiopen(_S, _M)) == 0)
return (0);
_Init(_Fp, _Openfl);
_Initcvt();
return (this); }
/*
_M继续传递到__Fiopen
*/
extern _CRTIMP FILE *__cdecl __Fiopen(const char *,ios_base::openmode);


/*
再次跟踪
*/
CRTIMP2 FILE *__cdecl __Fiopen(const char *name,
ios_base::openmode mode)
{ // open a file
static const char *mods[] = {
"r", "w", "w", "a", "rb", "wb", "wb", "ab",
"r+", "w+", "a+", "r+b", "w+b", "a+b", 0};
static const int valid[] = {
ios_base::in,
ios_base::out,
ios_base::out | ios_base::trunc,
ios_base::out | ios_base::app,
ios_base::in | ios_base::binary,
ios_base::out | ios_base::binary,
ios_base::out | ios_base::trunc | ios_base::binary,
ios_base::out | ios_base::app | ios_base::binary,
ios_base::in | ios_base::out,
ios_base::in | ios_base::out | ios_base::trunc,
ios_base::in | ios_base::out | ios_base::app,
ios_base::in | ios_base::out | ios_base::binary,
ios_base::in | ios_base::out | ios_base::trunc
| ios_base::binary,
ios_base::in | ios_base::out | ios_base::app
| ios_base::binary,
0};
FILE *fp;
int n;
ios_base::openmode atefl = mode & ios_base::ate;
mode &= ~ios_base::ate;

/*在下面将OpenMode映射到C的fopen的mode参数*/
for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
;


if (valid[n] == 0 || (fp = fopen(name, mods[n])) == 0)
return (0);
if (!atefl || fseek(fp, 0, SEEK_END) == 0)
return (fp);
fclose(fp); // can't position at end
return (0);
}
/*
在这里就很明显了,直到最终调用C的函数fopen,openmode的值始终没有被赋给fstream的对象.
*/


/*至于flag的值,是在基类里被初始化的,用的是默认值*/


explicit basic_iostream(basic_streambuf<_E, _Tr> *_S)
: basic_istream<_E, _Tr>(_S), basic_ostream<_E, _Tr>(_S, false, false)
{}

template<class _E, class _Tr = char_traits<_E> >
class basic_ostream : virtual public basic_ios<_E, _Tr> {}

explicit basic_ostream(basic_streambuf<_E, _Tr> *_S,
bool _Isstd = false, bool _Doinit = true)
{if (_Doinit)
init(_S, _Isstd); }

/*init()在基类basic_ios里定义,这个派生类里没有改写*/



explicit basic_ios(_Mysb *_S)
{init(_S); }

void init(_Mysb *_S = 0,
bool _Isstd = false)
{_Sb = _S;
_Tiestr = 0;
_Fillch = _WIDEN(_E, ' ');
_Init();
if (_Sb == 0)
setstate(badbit);
if (_Isstd)
_Addstd();
}
/*这里继续调用_Init()*/

void ios_base::_Init()
{ // initialize a new ios_base
new (&_Loc) locale;
_Except = goodbit;
_Fmtfl = skipws | dec; /*Flag 值在这里被初始化*/
_Prec = 6;
_Wide = 0;
_Arr = 0;
_Calls = 0;
clear(goodbit);
}

/*参看一下flags函数*/
fmtflags flags() const
{return (_Fmtfl); }

fmtflags flags(fmtflags _Nf)
{fmtflags _Of = _Fmtfl;
_Fmtfl = _Nf & _Fmtmask;
return (_Of); }


/*从上面的源码跟踪可以发现, STL并没有对这种打开文件传递进去的OpenMode参数进行保存,
所以如果用fstream打开文件时就将OpenMode作为第二个参数传递进去,想直接从fstream对象取得OpenMode不可行
*/
ccom 2003-07-14
  • 打赏
  • 举报
回复
好像不可能吧,大部分是根据后缀去判断是不是文本文件,君不见好多FTP软件,总要让你选择是按文本方式还是二进制方式,他们就是按照后缀判断的。
wintersun 2003-07-14
  • 打赏
  • 举报
回复
首先取出Flag值,以下面的方式:
long lFlag = outfile.flags();

然后再对照下面的表:
in = 0x01, out = 0x02, ate = 0x04,
app = 0x08, trunc = 0x10, binary = 0x20

不过,根据我的测试,打开文件时直接强Open Mode传递进去时Flag的值不正确:
ofstream outfile("pq.txt",ios_base::binary | ios_base::app);

需要调用setf或者Flags,下面我试验可行的操作:
ifstream outfile("pq.txt");
outfile.setf(ios_base::binary | ios_base::app);
long lFlag=outfile.flags();
/*lFlag=0x22B 0x22B==0x200+0x20+0x08+0x02+0x01,即 0x200+binary+app+out+in*/

不过这样的操作的确让人不大满意,不知道有更好没有好的方法了.

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧