C: Запись и чтение строки в двоичный файл и из него - PullRequest
1 голос
/ 10 марта 2010

Я хочу хранить строки в двоичном файле вместе с множеством других данных. Я использую приведенный ниже код (когда я использую его для реального, строки будут malloc'd), я могу записать в файл. Я посмотрел на это в шестнадцатеричном редакторе. Я не уверен, что я пишу нулевой терминатор правильно (или, если мне нужно). когда я читаю обратно, я получаю ту же самую длину строки, которую я сохранил, но не строку. что я делаю не так?

FILE *fp = fopen("mybinfile.ttt", "wb");

char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);    
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);

//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);

fclose(fp);

fp = fopen("mybinfile.ttt", "rb");  

unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);

char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);

//CRASH POINT
printf("%s\n", drumReadString);

fclose(fp); 

Ответы [ 6 ]

7 голосов
/ 10 марта 2010

Вы делаете неправильно во время чтения. Вы указали переменную & для указателя, поэтому она дает ошибку сегментации.

Я убрал, что он работает нормально и возвращает Hello правильно.

int count = fread(drumReadString, sizeof(char), stringLength, fp);
6 голосов
/ 10 марта 2010

Я вижу пару вопросов, некоторые проблемные, некоторые стилистические.

  • Вы должны действительно проверить возвращаемые значения из malloc, fread и fwrite, поскольку вполне возможно, что распределение может завершиться неудачно, и никакие данные не могут быть прочитаны или записаны.
  • sizeof(char) - это всегда 1, умножать его не нужно.
  • Массив символов "Hello\0" на самом деле имеет длину 7 байтов. Вам не нужно добавлять лишний нулевой терминатор.
  • Я предпочитаю идиому char x[] = "xxx";, а не указание определенной длины (если, конечно, вы не хотите, чтобы массив был длиннее строки).
  • Когда вы fread(&drumReadString ..., вы на самом деле перезаписываете указатель , а не память, на которую он указывает. Это причина вашего крушения. Это должно быть fread(drumReadString ....
5 голосов
/ 10 марта 2010

Пара советов:

1

Завершение \0 подразумевается в любой строке двойных кавычек, и, добавив дополнительный в конце, вы получите два. Следующие две инициализации идентичны:

char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};

So

char drumReadString[] = "Hello";

достаточно, и указание размера массива необязательно, когда он инициализируется следующим образом, компилятор определит требуемый размер (6 байт).

2

При написании строки вы можете просто написать все символы за один раз (вместо того, чтобы писать по одному размеру sizeOfString раз):

fwrite(drumCString, sizeOfString, 1, fp);

3

Даже если это не так часто встречается в обычном настольном компьютере, malloc может вернуть NULL, и вы выиграете от привычки всегда проверять результат, потому что во встроенных средах получение NULL не является вероятным результатом.

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}
0 голосов
/ 10 марта 2010

Вы просто удаляете свою & drumReadString в функции fread. Вы просто используете drumReadString в этой функции, как упоминалось Ганешем. Потому что drumReadString - это массив. Массив похож на указатели, которые указывают непосредственно на ячейку памяти.

0 голосов
/ 10 марта 2010

Еще немного добавить к paxdiablo и AProgrammer - если вы собираетесь использовать malloc в будущем, просто сделайте это с самого начала. Это лучшая форма и означает, что вам не придется отлаживать при переключении.

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

0 голосов
/ 10 марта 2010

Вы не пишете завершающий NUL, вам не нужно, но тогда вы должны подумать о добавлении его при чтении. то есть malloc stringLength + 1 char, прочитайте stringLength chars и добавьте \0 в конце прочитанного.

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

...