繁体   English   中英

C:在二进制文件中读写字符串

[英]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);

我看到了几个问题,一些问题,一些风格。

  • 您应该真正测试mallocfreadfwrite的返回值,因为分配可能会失败,并且不会读取或写入任何数据。
  • 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

编写字符串时,您可能还一口气写了所有字符(而不是一字符一倍地写sizeOfString次):

fwrite(drumCString, sizeOfString, 1, fp);

3

即使在普通的台式机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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM