Неправильный вывод бинарного файла с использованием _tprintf

Я должен прочитать двоичный файл, но у меня неправильный вывод. Я начинаю с текстового файла, который содержит:

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

Я генерирую относительный двоичный файл с помощью программы:

#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;
}

Теперь я думаю, что это дает мне двоичный файл. Затем я должен прочитать этот двоичный файл и поместить данные в структуру. Мой код:

#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;
}

Теперь в этой части кода

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);
        }

вывод неверен, то есть: введите здесь описание изображения

Почему я получаю это? Я генерирую неправильный bin-файл? Или мне плохо удается функция вывода? Я надеюсь, что вы можете мне помочь. Заранее спасибо.


person Develobeer    schedule 15.05.2015    source источник
comment
Вы буквально дублируете свой текстовый файл. Вся ваша первая программа могла быть написана одним вызовом Win32 API, Копировать файл. То, что вы реплицировали файл, не превращает его волшебным образом в структурированный макет, который вы, кажется, ожидаете от своего второго кода. Мне кажется, что ваша первая программа должна читать текст, преобразовывать его в нужный вам структурированный макет, а затем писать это.   -  person WhozCraig    schedule 16.05.2015
comment
Как вам сказали в другом обсуждении, ваш входной файл НЕ БИНАРНЫЙ ФАЙЛ, это ТЕКСТОВЫЙ ФАЙЛ. Он НЕ содержит двоичных структур, поэтому перестаньте пытаться читать его так, как если бы он был. Прочитайте его как текстовый файл. Используйте стандартный класс std::ifstream, чтобы открыть его, затем вы можете использовать такие вещи, как operator>> или std::getline() и std::istringstream, чтобы читать и анализировать текст по мере необходимости. Чтение необработанных байтов исходного файла и запись их как есть в другой файл не создает автоматически двоичный файл. Вы должны КОНВЕРТИРОВАТЬ данные.   -  person Remy Lebeau    schedule 16.05.2015
comment
вы можете посмотреть этот ответ: ‹stackoverflow.com/questions/1319461/› в отношении использования обычного текста или использования юникода. Вы изучили созданный файл, чтобы узнать, каково его фактическое содержимое?   -  person user3629249    schedule 17.05.2015


Ответы (1)


Вы считаете, что вторая программа неверна, но мы не знаем, так ли это, потому что ввод для второй программы также неверен.

Предполагается, что ввод для второй программы (также вывод первой программы) должен быть двоичным файлом, но на самом деле это текстовый файл, идентичный вводу первой программы. Это идентично, потому что первая программа не выполняет никаких преобразований. Все, что он делает, это ReadFile(..., buffer, ..., &nIn, ...), за которым сразу следует WriteFile(..., buffer, nIn, ...). Эти две строки просто копируют все данные.

Первая программа должна использовать getline() (как описано здесь, во втором методе, синтаксический анализ на основе строк) вместо ReadFile(), получить все данные, заполнить один struct myacc объект и WriteFile содержимое этого объекта.

person Dialecticus    schedule 16.05.2015