开发者

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

开发者 https://www.devze.com 2023-02-20 18:43 出处:网络
When trying to come up with an answer to this question, I wrote this little test-program: #include <iostream>

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<开发者_JAVA技巧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?


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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消