2014-02-12 3 views
4
struct book 
{ 
    unsigned short size_of_content; 
    unsigned short price; 
    unsigned char *content; 
}; 

Предположим, у меня есть файл, который содержит несколько book с, каждый из них имеет разные size_of_content, price и content. Как я могу прочитать их один book за раз и определить, какая именно книга (например, цена проверки)?Как fread() structs?

size_t nread2; 
struct book *buff = malloc(sizeof(struct book)); 
while((nread2 = fread(buff, sizeof(struct book), 1, infp)) > 0) 
{ 
    printf("read a struct once \n"); 
} 

Это то, что у меня есть до сих пор. Я пытался распечатать всякий раз, когда я читал структуру. Однако, когда я попробовал входной файл с 5 структурами, он будет печатать 15 раз ...

Спасибо.

+0

Каков формат файла, который вы пытаетесь прочитать? – Maxpm

+0

@Maxpm может быть чем угодно, но тестовый файл у меня есть файл bin. – Pig

+1

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

ответ

7

Давайте посмотрим на ваш struct и подумаем о том, насколько он большой.

struct book { 
    unsigned short size_of_content; 
    unsigned short price; 
    unsigned char *content; 
}; 

Первый элемент является unsigned short, не проблема, sizeof(unsigned short), вероятно, будет 2, как и в 2 байта. Аналогично следующий.

Но этот третий. Это указатель на unsigned char ... ваши записи на диске вряд ли сохранены указатели. У вас есть поле size_of_content ... я предполагаю, что записи диска содержат size_of_content, затем price, а затем фактическое содержимое.

Я не буду писать полный код для вас, но в псевдокоде это идет что-то вроде этого:

fread(&size_of_content, sizeof(size_of_content), 1, infp) 
sanity-check the value of size_of_content and handle any error 
fread(&price, sizeof(price), 1, infp) 
sanity-check teh value of price and handle any error 
buff->content = malloc(size_of_content) 
check for error on malloc and handle any error 
fread(buff->content, size_of_content, 1, infp) 

Если вы не имеете негибкие спецификаций для того, как большого содержания может просто предположите, что это не может быть больше миллиарда или что-то в этом роде, и убедитесь, что число по крайней мере не так велико! Всегда проверяйте наличие ошибок.

Поскольку в struct есть только два поля, это довольно просто: fread() каждый. Если вы имели более сложную структуру, то может быть стоит использовать:-структуру

struct book_header { 
    unsigned short size_of_content; 
    unsigned short price; 
}; 

struct book { 
    struct book_header header; 
    unsigned char *content; 
} 

Затем вы можете использовать fread() с sizeof(book_header) читать весь заголовок на одном дыхании. Я написал много кода, например, при работе с бинарными файлами, такими как звуковые файлы с волнами.


Вы, наверное, не нужно беспокоиться об этом, но это было бы проблемой, если файл был написан на «большой Endian» компьютер и читать на «прямой порядок байтов» компьютер, или наоборот -versa.

http://en.wikipedia.org/wiki/Endianness

Если вы имели эту проблему, решение стандартизировать. Выберите либо один (маленький-endian или big-endian), и используйте библиотечную функцию C, чтобы убедиться, что числа написаны и прочитаны с использованием этой цели. Например, функция библиотеки htonl() при записи и ntohl() при чтении.

http://linux.die.net/man/3/htonl

Но, как я сказал, вы, вероятно, не нужно беспокоиться об этом.

+0

Это просто произвольный вопрос, фактический размер контента будет не очень большим? – Pig

+0

У меня нет возможности догадаться, насколько велик фактический размер контента, но я бы не ожидал, что он будет большим. Вы можете посмотреть размер входного файла, и вы знаете, что это должно быть пять записей, поэтому они, вероятно, составляют около 1/5 от размера файла или что-то в этом роде. – steveha

+0

Спасибо большое! Одна вещь, которую я все еще не уверен, заключается в том, что, поскольку в файле есть несколько книг, как можно узнать, что искать? – Pig