как читать содержимое структуры, используя fread () в c - PullRequest
0 голосов
/ 01 декабря 2011

У меня есть следующий код, где я пытаюсь прочитать содержимое файла и отобразить его, а также записать в другой файл.Моя проблема в том, что содержимое, которое я получаю на экране, полностью отличается от содержимого файла.Я поместил части содержимого файла и части отображаемого результата

#include<iostream>
#include <stdint.h>
#include <stdio.h>
struct test
{
uint64_t start;
uint16_t length;
struct test *next;   
};

void main()
{
    char frd[32];
        std::cout<<"\nEnter name of file to read?\n";
    std::cin>>frd;
    FILE *rd=fopen(frd,"r+b");
    FILE *wrt=fopen("abc2.doc","w+");
     struct test test_st;

    while(fread (&test_st, sizeof(test_st), 1, rd))
{
       fwrite (&test_st,sizeof(test_st),1,wrt);
    printf("%llu,%u\n", test_st.start, test_st.length);
 }
fclose(rd);
fclose(wrt);
}

Частичное содержимое исходного файла:

0,43 
43,95 
138,159
297,279
576,153
729,64

Первые несколько строк отображаемого результата:

3474018176930688048,13879
3472896773804077344,14136
4049914982932231728,13362
3978707281317738034,12342
3474306356368193848,14132
3688511012684903220,14130
724298015681099573,13624

Исходные и конечные файлы имеют точные копии

Ответы [ 4 ]

2 голосов
/ 01 декабря 2011

Ваш файл не содержит структуру, он содержит значения, разделенные запятыми (текстовое представление данных).

Структура хранится в двоичной форме, а не в текстовой форме.

Когда вы читаете, ваша программа пытается интерпретировать прочитанное как двоичное.Отмените это:

$ printf "%x%x" 3474018176930688048 13879 | sed 's/../\\\\x&/g' | sed 's/^/echo -e /e'
061 34,067

Чтобы прочитать данные, хранящиеся в текстовой форме, вы можете прочитать каждую строку с помощью fgets, а затем проанализировать ее (например, используя sscanf()).

1 голос
/ 01 декабря 2011

Вот некоторый рабочий код. Я оставил часть письма, так как не знаю, какой вывод вы ищете. Просто пройдите логику чтения, и вы поймете, как исправить записывающую часть.

Я оставил там отладочный файл printf, чтобы вы могли понять, как работает код и как анализируются файлы csv для получения результатов, которые вы ищете. Как упоминалось выше, файл представляет собой текстовый файл (CSV), а не двоичный файл. То, как вы пытаетесь его прочитать, предназначено для чтения двоичных файлов. Так что такой подход не поможет. Теперь для чтения бинарных файлов вы должны хранить их как двоичные файлы.

#include <iostream>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

struct test {
  uint64_t start;
  uint16_t length;
  struct test *next;   
};

int main(void)
{
  char frd[32];
  std::cout<<"\nEnter name of file to read?\n";
  std::cin>>frd;
  FILE *rd=fopen(frd,"r+b");
  FILE *wrt=fopen("abc2.doc","w+");
  struct test test_st;
  char readLine[100];

  while(fgets(readLine, 100, rd) != NULL) {
    // Removing the new line from the end
    // This is a quick hack as Windows have two characters
    // to represent new line. It is not needed to remove newline.
    // I did so that printf output look pleasing
    readLine[strlen(readLine) - 1] = '\0';
    printf("\nr=%s", readLine);

    // Splitting the string based on ','
    // and then converting it to number
    char *token = NULL;
    token = strtok(readLine, ",");
    test_st.start = atol(token);
    printf("\nt1=%s, test_st.start=%llu", token, test_st.start);

    token = strtok(NULL, ",");
    test_st.length = atoi(token);
    printf("\nt2=%s,test_st.length=%d", token, test_st.length);
    //fwrite (&test_st,sizeof(test_st),1,wrt);
    //printf("%llu,%u\n", test_st.start, test_st.length);
  }
  fclose(rd);
  fclose(wrt);
  return 0;
}
1 голос
/ 01 декабря 2011

Нет смысла писать указатель на файл. Код, который читает этот указатель, не будет иметь такого же представления о памяти, как код, который его написал. Так что не делай этого.

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

Тогда, если у вас возникнут проблемы, вы будете знать, в чем виноваты. Проверьте байты в файле и убедитесь, что они соответствуют определению. Если нет, то это вина автора. Если это так, то это вина читателя.

0 голосов
/ 01 декабря 2011

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

FILE *wrt=fopen("abc2.doc","w+b"); //instead of "w+"
...