Hos*_*ork 6 c++ text iostream binary-data
我一直试图阅读iostream并更好地理解它们.偶尔我发现它强调inserters(<<)和extractors(>>)意味着在文本序列化中使用.这是一些地方,但这篇文章是一个很好的例子:
http://spec.winprog.org/streams/
在<iostream>宇宙之外,有些情况下<<和>>以类似流的方式使用但不遵守任何文本约定.例如,他们在Qt使用时编写二进制编码数据QDataStream:
http://doc.qt.nokia.com/latest/qdatastream.html#details
在语言层面,<<和>>运算符属于你的项目要重载(因此QDataStream的作用显然是可以接受的).我的问题是那些使用<iostream><<和>>运算符来实现二进制编码和解码的人是否被认为是一种不好的做法.是否(例如)有任何期望,如果写入磁盘上的文件,该文件应该可以使用文本编辑器查看和编辑?
如果一个总是使用其他方法名称和基地他们read()和write()?或者文本编码应该仅仅被视为默认行为,与标准库iostream集成的类可以选择忽略?
更新关于此的一个关键术语问题似乎是"格式化"与"未格式化"的I/O的区别(与术语"文本"与"二进制"相对).我发现了这个问题:
将二进制数据(std :: string)写入std :: ofstream?
来自@ TomalakGeret'kal的评论说:"我不想使用<<用于二进制数据,因为我的大脑将其视为"格式化输出",这不是你正在做的事情.再次,它完全有效,但我不会那样混淆我的大脑."
这个问题的公认答案说只要你使用就可以了ios::binary.这似乎支持了辩论的"它没有任何问题"...但我仍然没有看到任何权威来源的问题.
实际上是运算符<<和>>位移运算符; 严格来说,将它们用于I/O已经是一种误用.然而,误操作与操作员超载本身一样久,今天的I/O是它们最常见的用法,因此它们被广泛认为是I/O插入/提取操作符.我很确定如果没有iostreams的先例,没有人会将这些运算符用于I/O(特别是对于具有可变参数模板的C++ 11,解决了使用这些运算符解决了iostreams的主要问题,更干净的方式).另一方面,从语言的角度来看,超载operator<<并且operator>>可以表示你想要的任何意思.
所以问题归结为对这些运营商的可接受使用.为此,我认为必须区分两种情况:第一,在iostream类上工作的新重载,第二,在其他类上工作的新重载,可能设计为像iostream一样工作.
让我们考虑iostream类上的第一个新运算符.让我首先观察iostream类是关于格式化的(和反向过程,可以称为"deformatting";"lexing"恕我直言,因为提取器不确定类型,但只尝试根据给定的类型解释数据).负责原始数据的实际I/O的类是streambufs.但请注意,正确的二进制文件不是您只是转储内部原始数据的文件.就像文本文件一样(实际上更是如此),二进制文件应该对它包含的数据进行明确的编码.特别是如果期望在不同系统上读取文件.因此,格式化输出的概念对二进制文件也很有意义; 只是格式化是不同的(例如,写入预定数量的字节,其中最重要的字节首先是整数值).
iostream本身是用于处理文本文件的类,即在其内容被解释为数据的文本表示的文件上.为此优化了许多内置行为,如果在二进制文件上使用,可能会导致问题.一个明显的例子是默认情况下,在尝试任何输入之前会跳过空格.对于二进制文件,这显然是错误的行为.同样,locales的使用对于二进制文件没有意义(尽管有人可能认为可能存在"二进制语言环境",但我不认为为iostream定义的语言环境为其提供了合适的接口).因此,我会说写二进制operator<<或operator>>iostream类是错误的.
另一种情况是为二进制输入/输出定义一个单独的类(可能重用streambuf层来执行实际的I/O).由于我们现在谈论不同的类别,上面的论证不再适用.所以,现在的问题是:应该operator<<和operator>>在I/O被视为"文本插入/拔出运营商"或更一般地称为"格式化数据插入/拔出运营商"?标准类仅将它们用于文本,但是,根本没有用于二进制I/O插入/提取的标准类,因此标准用法无法区分这两者.
我个人会说二进制插入/提取足够接近文本插入/提取,这种用法是合理的.请注意,您还可以制作有意义的二进制I/O操纵器,例如bigendian,littleendian并intwidth(n)确定输出整数的格式.
除此之外,还有那些操作符用于非I/O(以及你甚至不会想到使用streambuf层)的东西,比如读取或插入容器.在我看来,这已经构成对运营商的滥用,因为数据没有被翻译成不同的格式.它只是存储在一个容器中.