1

Again I've got a little problem with my DLL:

I try to convert a number (in this case "20") to a char which I can write to the file. It doesn't really matter in which way this is done (whether following the ascii-table or not), but I need a way to convert back as well.

This was my attempt:

file.write((char*)20,3);

But it's throwing an access violence error..

Could someone tell me how this is done and also how I can reverse the process? I could also use a method which works with numbers larger than 255 so the result are for example two or three chars (two chars = 16-bit-number.

Anyone have an idea?

DragonGamer
  • 834
  • 3
  • 9
  • 27

2 Answers2

2

If you just want to write an arbitrary byte, you can do this:

 file.put(20); 

or

 char ch = 20;

 file.write(&ch, 1);   // Note a higher digit than 1 here will mean "undefined behaviour". 

To reverse the process, you'd use file.get() or file.read(&ch, 1).

For larger units than a single byte, you'll have to use file.write(...), but it gets less portable, since it now relies on the size of the value being the same between different plaforms, AND that the internal representation is the same. This is not a problem if you are always running this on the same type of machine (Windows on an x86 processor, for example), but it will be a problem if you start using the code on different types of machines (x86, Sparc, ARM, IBM mainframe, Mobile phone DSP, etc) and possibly also between different OS's.

Something like this will work with the above restrictions:

int value = 4711;
file.write((char *)&value, sizeof(value));

It is much more portable to write this value to a file in text-form, which can be read by any other computer than recognises the same character encoding.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Ahhh, thank you very much! So I just forgot the "&" sign... A quick question again: Would file.read(temp_bytes, 2); int data_position = *(short *)temp_bytes; work to reverse the process and read two bytes back into an int? Portability is not really the issue since the DLL will be Windows-x86 - only anyways. EDIT: Is the a way to respond properly with a formatted message to a comment here? > – DragonGamer Jul 19 '13 at 17:17
  • `int data_position = *(short *)temp_bytes;` is probabloy not what you wan - that will try to read memory at address `temp_bytes`, which is almost certainly not what you want to do. Maybe you were looking for `int data_position = *(short *)&temp_bytes;` but not quite sure if that is what you were looking for. Why not just read it into a `temp_bytes` that is a `short` in the first place. And no, formatting is not easy/working in comments. – Mats Petersson Jul 19 '13 at 17:27
  • Ah okey.. but reading into a variable which has been defined as a short doesn'Ät work with file.read. It requires a char*... I'll try the method with &. Lol, I have to eventually get what "&" does at all... – DragonGamer Jul 19 '13 at 17:38
  • No, you have to cast it to a `char*`, but it works with other types as long as you do that. – Mats Petersson Jul 19 '13 at 17:39
0

This will convert an unsigned long long into multiple characters depending on how big the number is, and output them to a file.

#include <fstream>

int main() {
    unsigned long long number = 2098798987879879999;

    std::ofstream out("out.txt");

    while (number) { // While number != 0.
        unsigned long long n = number & 255; // Copy the 8 rightmost bits.
        number >>= 8; // Shift the original number 8 bits right.
        out << static_cast<unsigned char>(n); // Cast to char and output.
    }

    out << std::endl; // Append line break for every number.
}

You can read it back from a file using something like this

#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>

int main() {
    std::ifstream in("out.txt");

    unsigned long long number = 0;

    std::string s;
    std::getline(in, s); // Read line of characters.
    std::reverse(begin(s), end(s)); // To account for little-endian order.

    for (unsigned char c : s) {
        number <<= 8;
        number |= c;
    }

    std::cout << number << std::endl;
}

This outputs

2098798987879879999
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • Might want to note that it outputs things in little-endian order. As long as it's read back in an analogous way, this shouldn't be a problem, but it's something to be aware of, especially if you aren't working with a little-endian system... – twalberg Jul 19 '13 at 18:16