0

I created a read / write of bytes into a binary file using fstream object

#include <iostream>
#include <fstream>

using namespace std;

#define COL_WIDTH 20

int writeBinaryFile(char *desPath);
int readBinaryFile(char *desPath);

int age;
char name[COL_WIDTH];
int recsize = sizeof(int)+sizeof(name);
int n;

int main(){

    char desPath[MAX_PATH+1];
    char input[2];

    while(true){
        cout  << "Main Menu:\n1 Write Binary File\n2 Read Binary File\n3 EXIT" << endl;
        cin.getline(input, 2);          


        if(atoi(input)== 1){
            cout << "Enter destination path:" << endl;
            cin.getline(desPath, MAX_PATH+1);
            for(;;){
                int output = writeBinaryFile(desPath);
                if(output == 1) break;
                else if(output == 2) { *input = '4'; break;}
            }
        }
        else if(atoi(input) == 2){
            cout << "Enter destination path:" << endl;
            cin.getline(desPath, MAX_PATH+1);
            for(;;){
                int output = readBinaryFile(desPath);
                if(output == 1) break;
                else if(output == 2){ *input = '4'; break;}
            }
        }

        else if(atoi(input) == 3)
            break;
        else cout << "You entered wrong input, enter only 1 or 2." << endl;

        if(atoi(input) == 4) continue;
        else break;

    }

    system("pause");
    return 0;   
}

int writeBinaryFile(char *desPath){
    char option[2];
    fstream wBin(desPath, ios::binary | ios::out);
    if(!wBin){
        cout << desPath << " is not good path."<< endl;
        return 1;
    }
    cout << "Enter name: " << endl;
    cin.getline(name,COL_WIDTH);
    cout << "Enter age: " << endl;
    cin >> age;

    cout << "Enter record number: " << endl;
    cin >> n;

    wBin.seekp(n*recsize); 
    wBin.write(name, sizeof(name));
    wBin.write((char*)&age, sizeof(age));
    wBin.close();

    cout << "Enter record again? Press:" << endl
         << "Enter to continue" << endl
         << "Q to quit" << endl
         << "M to go back to main menu" << endl;

    cin.ignore(256,'\n');
    cin.getline(option,2);

    if(option[0] == 'q' ||option[0] == 'Q') return 1;
    else if(option[0] == 'm' ||option[0] == 'M') return 2;

    return 0;
}


int readBinaryFile(char *desPath){       
    char option[2];
    fstream rBin(desPath, ios:: binary | ios:: in);
    if(! rBin){
        cout << "File not found!" << endl;
        return 1;
    }
    cout << "What record number?" <<endl;
    cin >> n;
    rBin.seekp((n*recsize));
    rBin.read(name,sizeof(name));
    rBin.read((char*)&age, sizeof(int));


    cout << name <<endl;
    cout << age << endl;
    rBin.close();
    cout << "Print more? Press enter. Press Q to QUIT or M to go back." << endl;
    cin.clear();
    cin.sync();
    cin.getline(option, 2);

    if(option[0] == 'q'|| option[0] == 'Q'){rBin.close(); return 1;}
    else if(option[0] == 'm' || option[0] == 'M'){rBin.close(); return 2;}

    return 0;
}

i created a binary file first with name, age, recordnumber ( position of bytes which is 0) then on second loop i input name, age, recordnumber 2. When i tried to read the first pair(char*, int) of bytes pos(0) but it returns wrong result but when i tried to read the last pair in pos(1) it returns correct result.

I also tried making 3 times the input, but only the last char* and int is correct.

Why is it getting wrong results in first bytes(name(20bytes),age(4bytes)) but getting correct it last bytes?

10
  • 2
    What is your question? What are your wrong and right results? Commented Nov 3, 2011 at 20:17
  • I don't immediately see anything wrong with it. I'd have to run it to find the problem. Have you stepped through it as it ran? Commented Nov 3, 2011 at 20:21
  • when i created the bin file i input ff: name:name1, age:1, recordnum:0 then on second loop name2,2,1 then on third loop name3,3,2...i expect to get when i enter 0 for recordnum ..name1, 1 but i just got blank,0...same with recordnum 1..but with recordnum 2, i did get correct which is name3, 3... Commented Nov 3, 2011 at 20:28
  • 1
    In each call to writeBinaryFile the output is reopened, destroying the previous contents of the file. Commented Nov 3, 2011 at 20:29
  • 1
    Yes but as @Rob said, since you're opening it with only ios::out, the previous file contents will be destroyed. You'll want to use ios::binary | ios::ate | ios::out | ios::in Commented Nov 3, 2011 at 20:37

1 Answer 1

2

In each call to writeBinaryFile the output is reopened, destroying the previous contents of the file.

You'll want to use ios::binary | ios::ate | ios::out | ios::in.

But, this bitmask will not create the file if it does not exist. You can work around that problem with this code sequence:

int writeBinaryFile(char *desPath) {
  ...
  // Create the file only if it doesn't exist
  fstream(desPath, ios::binary|ios::out|ios::app);

  // Now it exists -- open it
  fstream wBin(desPath, ios::binary|ios::out|ios::in);
  ...
}

Credit @JoeFish for the useful part of the answer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.