Is it OK to use iostreams with int as character-type?

谁说我不能喝 提交于 2019-12-18 16:47:10

问题


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?


回答1:


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.)




回答2:


It works as expected.

I'm not sure what you are expecting...

Is this allowed?

That's probably not portable. Streams relies on char_traits and on facets which are defined in the standard only for char and wchar_t. An implementation can provides more, but my bet would be that you are relying on a minimal default implementation of those templates and not on a conscious implementation for int. I'd not be surprised that a more in depth use would leads to problems.



来源:https://stackoverflow.com/questions/5497284/is-it-ok-to-use-iostreams-with-int-as-character-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!