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

时间:2010-03-10 08:47:27

标签: c string binaryfiles

我想将字符串存储在二进制文件中,以及许多其他数据,我使用下面的代码(当我真正使用它时,字符串将被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 个答案:

答案 0 :(得分:7)

阅读时你做错了。 你放了&对于指针变量,这就是它给出分段错误的原因。

我删除了它工作正常,它正确返回Hello。

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

答案 1 :(得分:6)

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

  • 您应该真正测试mallocfreadfwrite的返回值,因为分配可能会失败,并且不会读取或写入数据。
  • sizeof(char) 总是 1,没有必要乘以它。
  • 字符数组"Hello\0"实际上是7个字节长。您不需要添加多余的null终止符。
  • 我更喜欢成语char x[] = "xxx";,而不是指定一个确定的长度(除非你想要一个比字符串更长的数组)。
  • 当你fread(&drumReadString ...时,你实际上是在覆盖指针,而不是它指向的内存。这是导致崩溃的原因。它应该是fread(drumReadString ...

答案 2 :(得分:5)

一些提示:

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;
}

答案 3 :(得分:0)

你没有写终止NUL,你不需要,但是你必须考虑在阅读时添加它。即malloc stringLength + 1 char,读取stringLength字符并在已读取的内容处添加\0

现在常见的警告:如果你按照你在这里的方式编写二进制文件,那么你有很多未说明的假设会使你的格式难以移植,有时甚至是同一编译器的另一个版本 - 我见过结构中的默认对齐在编译器版本之间发生变化。

答案 4 :(得分:0)

要添加到paxdiablo和AProgrammer还有更多内容 - 如果将来要使用malloc,只需从get get开始。它是更好的形式,意味着你不必在切换时进行调试。

此外,我还没有完全看到使用unsigned short,如果你打算编写一个二进制文件,请考虑unsigned char类型通常是大小字节,这使得它非常方便。

答案 5 :(得分:0)

你只需在fread函数中删除你的& drumReadString。你只需在该函数中使用drumReadString作为ganesh提到。因为,drumReadString是一个数组.Array类似于直接指向内存位置的指针。