3

In a game I'm making I need to read a map from a file. Assuming some of the data in the beginning is written in characters, but the tile map is written in binary, I would open the file in text mode then switch it to binary mode once it reaches the tile data.

Is there an easy, or standard, way of changing an ifstream from text mode to binary mode while keeping the same position in the file? This also applies to the writting part, I will need to start writting into the file using characters, then change to binary mode.

EDIT: I'm using text mode to make this readable and to read strings of unknown size. For example, this line:

map-name=TestMap

I'd read this with

getline( mapFile, attribute, '=' );
getline( mapFile, mapName, '\n' );

How would I read this in binary mode if there won't be newline characters?

jww
  • 97,681
  • 90
  • 411
  • 885
aslg
  • 1,966
  • 2
  • 15
  • 20
  • Can you give three examples: how do you open a file as binary, how do you open it as a text and what would a mixed mode file look like? – Johannes Aug 15 '14 at 14:43
  • 2
    Hybrid files are such a bad idea... – Deduplicator Aug 15 '14 at 14:45
  • 2
    I am not sure if you understand the difference between text and binary modes for streams. In your case you should use binary mode all the time - you can write characters to a stream in binary mode w/o problem. – Wojtek Surowka Aug 15 '14 at 14:46
  • 1
    You can read and write text perfectly well if you open in binary mode. The only differences between them is what happens to newlines (which means that seeking in text mode is unreliable). – molbdnilo Aug 15 '14 at 14:52
  • open( filename ) would open in text mode, open( filename, ios::binary ) would open in binary mode, right.. I wouldnt just change from one to the other... That was a dumb question.. – aslg Aug 15 '14 at 14:52
  • What platform are you on? On Windows opening a file in text mode means that it automatically maps between `\n` characters and `CR LF` sequences. There's no such mapping going on in *nix systems. – Ferruccio Aug 15 '14 at 15:04
  • Are you sure it's some in text and some in binary? Cos text in a binary file often looks like text of you try to cat it, or open it in an editor. – doctorlove Aug 15 '14 at 15:07
  • @Deduplicator I agree, sort of; putting binary data into a file whose structure is in text isn't a very good idea, but there's no problem with putting bits of text in a binary file. – James Kanze Aug 15 '14 at 16:08
  • @molbdnilo Line endings _and_ end of file. (Windows, for example, will recognize a byte with 0x1A as end of file in text mode.) – James Kanze Aug 15 '14 at 16:09
  • @JamesKanze: But if you're putting text in a binary file, might as well do so in binary mode rather than text mode. At least, if you control the file format. – Mooing Duck Aug 15 '14 at 16:28
  • @MooingDuck Certainly. In fact, _if_ you need to control the format (say because it requires a certain type of line ending), you have to use binary, even if the format is 100% text. I was just responding to the comment that line endings are the only difference. – James Kanze Aug 15 '14 at 19:08
  • Also see the discussion of using [`std::freopen`](https://stackoverflow.com/a/39758021/608639) (but it looks kind of hacky). It would be nice if someone provided a canonical answer with examples for BSDs, Linux, OS X, Solaris and Windows. – jww May 20 '18 at 18:30

2 Answers2

3

The mode is established when the file is opened, and cannot be changed later. If there is any binary data in the file, you must use binary mode. But where is the problem? You can read text in binary mode; line endings might appear a bit strange (but not if you also wrote it in binary mode), but otherwise, there should be no problem as long as the binary data actually is text.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • So if I write a newline character in binary mode, it will be a newline when I read it next and not a CR/LF combo? If so I can just use binary mode all the way. – aslg Aug 15 '14 at 16:15
  • @aslg In the end, characters are binary data too. In text mode, some characters (like `\n`) are treated specially. In binary, no. (In theory, if you read and write binary, you may end up with extra zero's at the end of the file. In practice, it's been ages since that was the case.) – James Kanze Aug 15 '14 at 19:06
  • *"But where is the problem?"* - `std::cin` is opened in text mode. C++ does not appear to have provisions for reading `cin` as a stream in binary mode. I thought I might do an end-around by switching it to binary once my `main` started executing. Also see [Read binary data from std::cin](https://stackoverflow.com/q/7587595/608639). – jww May 20 '18 at 18:17
1

If you are responsible for writing the files as well, the simplest (and perhaps sanest) solution might be to write two files.

One in text, for text you wish to be human readable.

And the second as binary, for things like maps. In fact that way you could have one binary map file for each map.

doctorlove
  • 18,872
  • 2
  • 46
  • 62
  • I guess I could separate the map into two files.. that actually sounds like a good idea. I could have meta data as text in one file and the tiles as binary in the other file. Though I have other things to add, like NPCs, enemy encounters.. I wonder if I should have various files for each map instead of a single file. – aslg Aug 15 '14 at 16:11