0

I must read a binary file, but I have wrong output. I start from a txt file that contains:

1 100000 Romano Antonio 1250
2 150000 Fabrizi Aldo 2245
3 200000 Verdi Giacomo 11115
4 250000 Rossi Luigi 13630

I generate the relative binary file by with program:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#define BUF_SIZE 1000

/*
 *  Problem1: use tchar.h and _tmain instead of
 *  int main (int argc, LPTSTR argv [])
 *  Sometimes it is needeed to see argv correctly
 */
int _tmain (int argc, LPTSTR argv [])
{
  HANDLE hIn, hOut;
  DWORD nIn, nOut;
  CHAR buffer [BUF_SIZE];

  if (argc != 3) {
    fprintf (stderr, "Usage: cp file1 file2\n");
    return 1;
  }

  hIn = CreateFile (argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /*Here hIn is created with read access*/
  if (hIn == INVALID_HANDLE_VALUE) {
    fprintf (stderr,
      "Cannot open input file. Error: %x\n", GetLastError ());
    return 2;
  }

  hOut = CreateFile (argv[2], GENERIC_WRITE, 0, NULL,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hOut == INVALID_HANDLE_VALUE) {
    fprintf (stderr,
      "Cannot open output file. Error: %x\n", GetLastError ());
    CloseHandle(hIn);
    return 3;
  }

  while (ReadFile (hIn, buffer, BUF_SIZE, &nIn, NULL) && nIn > 0) {
/*hIn is the handle to the read file, buffer is a pointer to the buffer that receives the data read 
from the file, BUF_SIZE is the maximum number of bytes to be read, &nIn is 
the pointer to the variable that receives the n° of bytes read*/
    /*
     *  Problem 2:
     *  During the last cycle less than BUF_SIZE characters may
     *  be read from file
     *  WriteFile (hOut, buffer, BUF_SIZE, &nOut, NULL);
     *  so write just the number of characters read
     */
    WriteFile (hOut, buffer, nIn, &nOut, NULL); /*I write in file related hOut, the content of read file hIn is in buffer, 
nIn is the n° of bytes to write, &nOut is a pointer to the variable that receives the number of bytes written*/
    if (nIn != nOut) {
      fprintf (stderr, "Fatal write error: %x\n", GetLastError ());
      CloseHandle(hIn); CloseHandle(hOut);
      return 4;
    }
  }

  CloseHandle (hIn);
  CloseHandle (hOut);
  return 0;
}

Now I think that it gives me a binary file. Then, I have to read this binary file and put the data into a struct. My code is:

#if 1
#define UNICODE
#define _UNICODE
#endif

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#define L 30+1
#define SETFILEPOINTER_OVERLAPPING 1
#define N 3
#define BUF_SIZE 1000

struct myacc {
    int id;
    long int acc_number;
    TCHAR surname[L];
    TCHAR name[L];
    int amount;
};

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hIn;
    OVERLAPPED ov = {0, 0, 0, 0, NULL};
    DWORD nIn,n;
    //TCHAR c;
    //TCHAR buffer[BUF_SIZE];
    LARGE_INTEGER filePos;
    struct myacc account;

    if(argc != N) {
        fprintf(stderr, "Error into arguments\n");
        return 1;
    }

    hIn = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hIn == INVALID_HANDLE_VALUE) {
            fprintf (stderr,"Cannot open input file. Error: %x\n", GetLastError ());
            return 2;
        }

    n=1;
    filePos.QuadPart = (n-1) * sizeof(struct myacc);

#if SETFILEPOINTER_OVERLAPPING
    SetFilePointerEx (hIn, filePos, NULL, FILE_BEGIN);
    while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, NULL) && nIn > 0) {
        _tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
    }
#else
    ov.Offset = filePos.LowPart; /*Uso l'overlapped structure ov se ho asynchronous I/O*/
    ov.OffsetHigh = filePos.HighPart;
    while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, &ov) && nIn > 0) {
        _tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
    }
#endif
    return 0;
}

Now, in this part of code

while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, NULL) && nIn > 0) {
            _tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
        }

the output is wrong, that is: enter image description here

Why do I get this? I generate wrong bin file? Or I manage bad the output function? I hope you can help me. Thank you in advance.

nanofarad
  • 36,174
  • 4
  • 79
  • 104
Anth
  • 249
  • 1
  • 3
  • 17
  • 2
    You're literally duplicating your text file. You're entire first program could have been written with a single win32 api call, [CopyFile](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851%28v=vs.85%29.aspx). Just because you replicated the file doesn't magically transform it into the structured layout you seem to be expecting with your second code. It seems to me your *first* program should be reading text, *translating* it into the structured layout you want, then writing *that*. – WhozCraig May 15 '15 at 23:51
  • As you were told in the [other discussion](http://stackoverflow.com/questions/30269383/), your input file is NOT A BINARY FILE, it is a TEXT FILE. It DOES NOT contain binary structures in it, so stop trying to read it as if it did. Read it as a text file. Use the standard `std::ifstream` class to open it, then you can use things like `operator>>`, or `std::getline()` and `std::istringstream`, to read and parse the text as needed. Reading the raw bytes of the original file and writing them as-is to another file does not automatically create a binary file. You have to CONVERT the data. – Remy Lebeau May 15 '15 at 23:57
  • you might want to look as this answer: in regards to using plain text or using unicode. Have you examined the produced file to see what its' actual contents are? – user3629249 May 17 '15 at 00:31

1 Answers1

1

You believe that second program is wrong, but we don't know if it is wrong because the input for the second program is also wrong.

Input for the second program (also output of the first program) is supposed to be a binary file, but it is actually a text file, identical to the the input of the first program. It is identical because the first program is not making any kind of conversion. All it does is ReadFile(..., buffer, ..., &nIn, ...) immediately followed by WriteFile(..., buffer, nIn, ...). These two lines just copy all the data.

First program should use getline() (like described here, in a second method, line-based parsing) instead of ReadFile(), get all the data, populate one struct myacc object, and WriteFile contents of that object.

Community
  • 1
  • 1
Dialecticus
  • 15,040
  • 5
  • 36
  • 88