2015-05-15 6 views
0

Мне нужно прочитать двоичный файл, но у меня неправильный вывод. Я начинаю с текстовый файл, который содержит:Неверный вывод из двоичного файла с помощью _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); 
     } 

выход неправильно, то есть: enter image description here

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

+2

Вы буквально дублируете свой текстовый файл. Вся первая программа могла быть написана с помощью одного вызова win32 api, [CopyFile] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851%28v=vs.85%29 .aspx). Просто потому, что вы реплицировали файл, он не волшебным образом преобразует его в структурированный макет, который, как вы ожидаете, со вторым кодом. Мне кажется, ваша * первая * программа должна читать текст, * переводить * его в структурированный макет, который вы хотите, а затем писать * это *. – WhozCraig

+0

Как вы сказали в [другом обсуждении] (http://stackoverflow.com/questions/30269383/), ваш входной файл НЕ БИНАРНЫЙ ФАЙЛ, это ФАЙЛ ТЕКСТА. Он НЕ содержит в себе двоичные структуры, поэтому перестаньте читать его, как если бы он это сделал. Прочитайте его как текстовый файл. Для его открытия используйте стандартный класс 'std :: ifstream', тогда вы можете использовать такие вещи, как' operator >> 'или' std :: getline() 'и' std :: istringstream', чтобы читать и анализировать текст как необходимо. Чтение необработанных байтов исходного файла и запись их как-в другой файл не создает двоичный файл автоматически. Вы должны преобразовывать данные. –

+0

, вы можете посмотреть, как этот ответ: в отношении использования обычного текста или используя unicode. Вы изучили подготовленный файл, чтобы узнать, каково его «фактическое содержание»? – user3629249

ответ

1

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

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

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