将iostream与int用作字符类型可以吗? [英] Is it OK to use iostreams with int as character-type?

查看:125
本文介绍了将iostream与int用作字符类型可以吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当试图给出对这个问题的答案时,我编写了这个小的测试程序:

  #include< iostream> 
#include< fstream>
#include< vector>
#include< iterator>
#include< algorithm>

void writeFile(){
int data [] = {0,1,2,3,4,5,6,7,8,9,1000};

std :: basic_ofstream< int> file( test.data,std :: ios :: binary);
std :: copy(data,data + 11,std :: ostreambuf_iterator< int>(file));
}

void readFile(){
std :: basic_ifstream< int> file( test.data,std :: ios :: binary);
std :: vector< int>数据(std :: istreambuf_iterator< int(文件),
(std :: istreambuf_iterator< int>()));

std :: copy(data.begin(),data.end(),
std :: ostream_iterator< int>(std :: cout,)));
std :: cout<< std :: endl;
}


int main()
{
writeFile();
readFile();

返回0;
}

它按预期工作,将数据写入文件,并在读取了文件,它可以正确打印:

  0 1 2 3 4 5 6 7 8 9 1000 

但是,我不确定是否存在任何陷阱(除了固有性问题,在处理二进制数据时总会遇到这些问题)?

解决方案

实例化除char或wchar_t之外的任何
上的任何iostream类或basic_string,没有提供特定的自定义特征类,
是未定义的行为;我见过的大多数库都将其定义为
做某事,但是通常没有指定该定义,并且VC ++和g ++之间的
是不同的(我研究过的两种情况)。如果
定义并使用自己的traits类,则某些功能应该
可以工作。



几乎所有格式化的插入器和提取器都适用(<
> 运算符), istream ostream 委托给
语言环境中的各个方面; (如果使用了其中任何一种),则必须采取措施,确保
都能正常使用。 (这通常意味着提供一个新的
numpunct构面。)



即使仅使用 streambuf (例如您的示例), filebuf
使用编解码器构面。而且不需要实现来提供
的编解码器,并且如果这样做,则可以在
中完成几乎所有的操作。而且,由于 filebuf 总是在
文件中写入和读取 char ,因此该翻译必须有所作为。因此,我实际上让
感到惊讶,因为您的代码有效。但是,您仍然不知道
磁盘上实际有什么内容,这意味着您无法对其进行记录,而
意味着您将来将无法读取它。

如果您的目标是写入二进制数据,则第一步应该是
定义二进制格式,然后编写由
实现的读取和写入函数。可能使用iostream<<和>>语法,以及
可能使用 basic_streambuf< char> 作为实际输入和
输出;一个 basic_streambuf< char> ,您已经对
C语言环境进行了精心设计。而不是定义自己的二进制格式,只需使用现有的
即可,例如XDR。 (本段全部假设您希望
保留数据并在以后读取。如果这些只是临时文件,则
用于在一次运行中将临时内部数据溢出到磁盘,而
将在程序执行结束时删除,更简单的解决方案
有效。)


When trying to come up with an answer to this question, I wrote this little test-program:

#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>

void writeFile() {
    int data[] = {0,1,2,3,4,5,6,7,8,9,1000};

    std::basic_ofstream<int> file("test.data", std::ios::binary);
    std::copy(data, data+11, std::ostreambuf_iterator<int>(file));
}

void readFile() {
    std::basic_ifstream<int> file("test.data", std::ios::binary);
    std::vector<int> data(std::istreambuf_iterator<int>(file),
        (std::istreambuf_iterator<int>()));

    std::copy(data.begin(), data.end(), 
              std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
}


int main()
{
    writeFile();
    readFile();

    return 0;
}

It works as expected, writing the data to the file, and after reading the file, it correctly prints:

0 1 2 3 4 5 6 7 8 9 1000

However, I am not sure if there are any pitfalls (endianess issues aside, you always have these when dealing with binary data)? Is this allowed?

解决方案

Instantiating any of the iostream classes, or basic_string, on anything but char or wchar_t, without providing a specific custom traits class, is undefined behavior; most of the libraries I've seen do define it to do something, but that definition often isn't specified, and is different between VC++ and g++ (the two cases I've looked at). If you define and use your own traits class, some of the functionality should work.

For just about all of the formatted inserters and extractors (the << and >> operators), istream and ostream delegate to various facets in the locale; if any of these are used, you'll have to take steps to ensure that these work as well. (This usually means providing a new numpunct facet.)

Even if you only use the streambuf (as in your example), filebuf uses the codecvt facet. And an implementation isn't required to provide a codecvt, and if it does, can do pretty much whatever it wants in it. And since filebuf always writes and reads char to and from the file, this translation must do something. I'm actually rather surprised that your code worked, because of this. But you still don't know what was actually on the disk, which means you can't document it, which means that you won't be able to read it sometime in the future.

If your goal is to write binary data, your first step should be to define the binary format, then write read and write functions which implement it. Possibly using the iostream << and >> syntax, and probably using a basic_streambuf<char> for the actual input and output; a basic_streambuf<char> that you've carefully imbued with the "C" locale. Or rather than define your own binary format, just use an existing one, like XDR. (All of this paragraph supposes that you want to keep the data, and read it later. If these are just temporary files, for spilling temporary internal data to disk during a single run, and will be deleted at the end of the program execution, simpler solutions are valid.)

这篇关于将iostream与int用作字符类型可以吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆