[英]C: Writing and Reading a string to and from a binary file
我想将字符串以及许多其他数据存储在二进制文件中,即时消息使用下面的代码(当我将其真正用于字符串时,将被malloc分配)我可以写入文件。 Ive在十六进制编辑器中查看了它。 我不确定我是否正确地写了空终止符(或者如果我需要)。 当我读回时,我得到与存储的相同的字符串长度,但不是字符串。 我究竟做错了什么?
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 ...
一些提示:
在任何双引号字符串中都隐含一个终止符\\0
,通过在末尾添加一个附加字符,您最终得到两个。 以下两个初始化是相同的:
char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};
所以
char drumReadString[] = "Hello";
这样就足够了,并且像这样初始化数组时,指定数组的大小是可选的,编译器将找出所需的大小(6个字节)。
编写字符串时,您可能还一口气写了所有字符(而不是一字符一倍地写sizeOfString次):
fwrite(drumCString, sizeOfString, 1, fp);
即使在普通的台式机PC场景中不太常见,malloc仍可以返回NULL,并且您将受益于开发一个始终检查结果的习惯,因为在嵌入式环境中,获得NULL的可能性不大。
char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
fprintf(stderr, "drumReadString allocation failed\n");
return;
}
您不必编写终止的NUL,也不必编写,但随后必须在阅读时考虑添加它。 即malloc stringLength + 1个字符,读取stringLength字符,并在已读取内容的末尾添加\\0
。
现在是通常的警告:如果您按照此处的方式编写二进制文件,则会有许多未声明的假设,这些假设使您的格式难以移植,有时甚至移植到同一编译器的另一个版本中-我已经在其中看到了默认对齐方式编译器版本之间的结构更改。
在paxdiablo和AProgrammer中添加了更多内容-如果将来要使用malloc,请从头开始。 这是更好的形式,这意味着切换时无需调试。
另外,我没有完全看到unsigned short的用法,如果您打算编写二进制文件,请考虑到unsigned char类型的大小通常为byte,因此非常方便。
您只需在fread函数中删除&drumReadString。您只需在ganesh中使用该函数中的drumReadString。因为,drumReadString是一个数组。Array与直接指向内存位置的指针相似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.