0

I am having this trouble - when I try to write binary of an integer to a file it doesn't write it in the Delivery file.

My whole idea was to take the integer, convert it to binary, write it to a file. After that if needed I'd come back to the program, write a new integer value and then add the new value to the already written one. i.e "5" in the file, come back, write "3" and then have 8 in the file.

Here is the code:

#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

char answer;

struct PRODUCT {
    string product_name;
    int quantity;
    PRODUCT() : product_name(""), quantity(0) {}
} product;

int main () {
    fstream delivery_file("files/Delivery", ios::app | ios::in | ios::out | ios::binary);
    do {

        if (delivery_file.is_open()) {
            cout << "\nPlease input the name of a product: ";

            getline(cin, product.product_name);

            cout << "\nPlease input the quantity of a product: ";
            string str;
            getline(cin, str);
            product.quantity = atoi(str.c_str());

            bool foundAndReplaced = false;

            while (!delivery_file.eof())
            {
                PRODUCT temp_prod;
                while (!delivery_file.eof())
                {
                    char ch = delivery_file.get();
                    temp_prod.product_name += ch;
                    if (ch == 0)
                    {
                        break;
                    }
                }
                if (delivery_file.eof() && delivery_file.tellg() == ios::beg)
                {
                    cout << "Error: Unexpected end of file.\n";
                    delivery_file.clear();
                    break;
                }
                if (temp_prod.product_name == product.product_name)
                {
                    delivery_file.seekp(delivery_file.tellg());
                    delivery_file.read((char*)(temp_prod.quantity), sizeof(PRODUCT::quantity));
                    product.quantity += temp_prod.quantity;
                    delivery_file.write((char*)(product.quantity), sizeof(PRODUCT::quantity));
                    foundAndReplaced = true;
                }
            }

            if (!foundAndReplaced)
            {
                delivery_file.write(product.product_name.c_str(), product.product_name.length() + 1);

                delivery_file.write((char*)(&product.quantity), sizeof(product.quantity));
            }

        }

        else {
            cout << "Unable to open file";
        }


        cout << "Do you want to add more products? Y/N \n";
        answer = 0;
        while (answer != 'y' && answer != 'Y' && answer != 'n' && answer != 'N')
        {
            answer = _getch();
        }
    }
    while(answer == 'Y' || answer == 'y');
    delivery_file.close();

    cout << "\nDeliveries registered.\n";

    return 0;
}
  • 3
    Don't post an external link. These can go stale. Post your code here (edit your question). Just add it to the question, select the code and press the `{}` toolbar button in the editor. That will format it as code. More here: https://meta.stackexchange.com/questions/22186/how-do-i-format-my-code-blocks . I copied the code from your link and posted it here. Next time, you should do that yourself. – Rudy Velthuis Jun 13 '18 at 09:54

1 Answers1

2

Using ios::binary does not cause it to write binary data into a file, it simply disables some of the formatting, see What the point of using std::ios_base::binary? for instance.

If you wish to write an integer to a file as binary, I suggest you use something like this:

int foo = 0x0F00;
ofstream bar("test.txt", ios::out | ios::binary);
bar.write(reinterpret_cast<char*>(&foo), sizeof(int));
bar.close();

This will take the integer, reinterpret it as a character sequence and output it to the file without formatting (ios::binary is needed for this).

Seeing as you've since edited the question: You can not sum like that on the disk, you can only write in bytes, this will overwrite any data that was there before. To do what you want you have to read the number, sum it up and then write it back down. You do that by using foo.read(...) with foo now being fstream and opened with ios::in as well.

Qubit
  • 1,175
  • 9
  • 18
  • My whole idea was to take the integer, convert it to binary, write it to a file. After that if needed I'd come back to the program, write a new integer value and then add the new value to the already written one. i.e "5" in the file, come back, write "3" and then have 8 in the file. – Angel Andreev Jun 13 '18 at 10:02
  • You can't write bits. To do what you want you'd have to read the value, sum them up and then write again, you can do that using `bar.read(...)`, but then `bar` should be `fstream` and opened with `ios::in` as well, much like in your example. I simply showed a minimal example of how to write binary to a file. – Qubit Jun 13 '18 at 10:09
  • Thank you for your comment. However, can you review the source I supplied in the main post, for some reason it doesn't write anything in "files/Delivery" – Angel Andreev Jun 13 '18 at 11:45
  • Generally I'd suggest testing new things on minimal examples first. Simply scrolling through the code I'd say you should look at the lines following `if (temp_prod.product_name == product.product_name)`, you need to cast a pointer to a pointer not a value to a pointer. Now you're just going to store the address (which makes little sense to store in a file). Another note, when outputting errors, use cerr rather than cout, it's not buffered so it's guaranteed to execute before anything goes terribly wrong. – Qubit Jun 14 '18 at 07:58