为新文件类型重载 >> 运算符的优雅方法是啥?
Posted
技术标签:
【中文标题】为新文件类型重载 >> 运算符的优雅方法是啥?【英文标题】:What's an elegant way to overload the >> operator for a new file type?为新文件类型重载 >> 运算符的优雅方法是什么? 【发布时间】:2013-02-14 18:48:23 【问题描述】:我正在向一些遗留代码添加一些新功能。现有代码从文本文件中读取一些数据。在新版本中,我将读取更多数据并希望使用二进制文件,除此之外,该程序可以在 Linux 或 Windows 上使用相同的(外部)数据文件,所以我想强制执行读取二进制数据时的大端意义。
为此,我创建了一个新的输入文件流类型 - 从 ifstream 继承 - 使用重载的“>>”运算符从文件中读取二进制数据,并将其解释为大端。到目前为止一切顺利。
现在,当我从文件中读取数据时,我需要选择要创建哪种类型的输入文件流对象:处理旧文本文件时的常规 ifstream 或处理新文本文件时的新“iBinFile”类型二进制文件。我能想到的唯一解决方案是使用两段不同的代码,一段用于旧类型,另一段用于新类型,除了输入文件流类型之外,它们是相同的:
if (szFileName.compare(szFileName.size()-3,3,"bin")==0)
iBinFile inFile(szFileName.c_str());
if (!inFile)
cout << szFileName <<" file could not be opened" << endl;
exit (-1);
while(!inFile.eof())
inFile >> data;
else
ifstream inFile(szFileName.c_str());
if (!inFile)
cout << szFileName <<" file could not be opened" << endl;
exit (-1);
while(!inFile.eof())
inFile >> data;
但我觉得因为 iBinFile 是从 ifstream 派生的,所以应该有一种方法可以做到这一点,其中 if
语句仅确定文件类型,其他一切都是共同的。如果我从我自己的类派生 iBinFile,那么我可以将“>>”运算符设为虚拟,但由于不是,我不知道解决方案是什么,如果有的话。
【问题讨论】:
只有一件事,while(!inFile.eof())
是不可以的!请改用while(inFile >> data) /* do stuff with data */
。
二进制文件不可移植。再次重申:二进制文件不可移植。如果你这样做,你会感到很头疼;字节序只是您必须处理的问题之一。您还必须为相同类型和值的不同二进制表示形式分类不同的大小。更不用说完全不习惯使用>>
,在正常使用中会进行格式化输入(即来自文本文件)。
@PeteBecker 二进制文件可以像文本文件一样便携。在这两种情况下,您都需要指定一种格式(或使用现有的格式,如 XDR 或 BER),然后写入和读取该格式。毕竟,许多可移植格式(例如 JPEG、MP3 等)是二进制的,我也在 IBM 大型机和 PC 之间以二进制进行通信(使用一种定义浮点的格式以 BCD 表示)。
@JamesKanze - 我坚持我所说的:除了字节顺序之外,您还必须处理相同类型的不同大小和值的不同二进制表示。将协议名称放在上面并不会改变根本问题。
@PeteBecker 您必须以 yoru 二进制格式定义类型的表示,是的。而且您必须确保您的写入和读取函数符合您定义的格式。但是,这可以便携式完成; BER 和 XDR 都很普遍,BER 经常用于在架构完全不同的处理器之间进行通信。
【参考方案1】:
所有当前 iostream 类的抽象是
格式化的文本。您确实不想从任何
std::istream
或 std::ostream
类;你想创建
你自己的层次结构。你可能确实想从
std::basic_ios<char>
,用于错误处理和streambuf
管理。同样,可能确实想使用streambuf
及其派生类。
【讨论】:
然后将两者包装在一个通用的提取器类中,该类可以采用istream
或您的二进制阅读器...
这可能有点棘手。我不太确定你会怎么做,因为>>
都不是虚拟的。
包装它——使用virtual operator>>
创建一个新类。创建两个实现,其中一个使用istream
,另一个使用您的二进制读取类。这种类的典型名称是InputArchive
。
现有的operator>>
不是成员,您甚至都不知道所有成员(因为大多数将用于用户定义的类型)。如果您想包装std::ostream
(我偶尔会这样做),您需要将operator>>
制作为模板。这意味着它不能是虚拟的。
+1 用于识别 istream 和 ostream 是格式化的文本类。以上是关于为新文件类型重载 >> 运算符的优雅方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章