C:Запись и чтение строки в двоичный файл и из него

StackOverflow https://stackoverflow.com/questions/2415495

  •  19-09-2019
  •  | 
  •  

Вопрос

Я хочу сохранить строки в двоичном файле вместе с множеством других данных, я использую приведенный ниже код (когда я использую его по-настоящему, строки будут 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); 
Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

1

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

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

Итак

char drumReadString[] = "Hello";

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

2

При написании строки вы могли бы с таким же успехом просто записать все символы за один раз (вместо того, чтобы писать один за другим character 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;
}

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top