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

发布于 2024-08-25 02:42:34 字数 852 浏览 0 评论 0原文

我想将字符串与许多其他数据一起存储在二进制文件中,我使用下面的代码(当我真正使用它时,字符串将被 malloc )我可以写入该文件。我在十六进制编辑器中看过它。我不确定是否正确编写了空终止符(或者是否需要)。当我读回时,我得到的字符串长度与我存储的相同,但不是字符串。我做错了什么?

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

I want to store strings in a binary file, along with a lot of other data, im using the code below (when i use it for real the strings will be malloc'd) I can write to the file. Ive looked at it in a hex editor. Im not sure im writing the null terminator correctly (or if i need to). when i read back out i get the same string length that i stored, but not the string. what am i doing wrong?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

执笔绘流年 2024-09-01 02:42:35

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

  • 您应该真正测试 mallocfreadfwrite 的返回值,因为分配可能会失败,并且可能不会读取任何数据或书面。
  • sizeof(char) 始终 1,无需乘以它。
  • 字符数组“Hello\0”实际上有7个字节长。您不需要添加多余的空终止符。
  • 我更喜欢习惯用语 char x[] = "xxx"; 而不是指定明确的长度(当然,除非您想要一个比字符串长的数组)。
  • 当您fread(&drumReadString ...)时,您实际上覆盖了指针,而不是它指向的内存。这就是崩溃的原因。它应该为 fread(drumReadString ... 。

I see a couple of issues, some problematic, some stylistic.

  • You should really test the return values from malloc, fread and fwrite since it's possible that the allocation can fail, and no data may be read or written.
  • sizeof(char) is always 1, there's no need to multiply by it.
  • The character array "Hello\0" is actually 7 bytes long. You don't need to add a superfluous null terminator.
  • I prefer the idiom char x[] = "xxx"; rather than specifying a definite length (unless you want an array longer than the string of course).
  • When you fread(&drumReadString ..., you're actually overwriting the pointer, not the memory it points to. This is the cause of your crash. It should be fread(drumReadString ....
薄荷港 2024-09-01 02:42:35

一些提示:

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

尽管对于普通台式电脑场景来说并不常见,但 malloc 可以返回 NULL,您将养成总是检查结果的习惯会受益匪浅,因为在嵌入式环境中,获得 NULL 并不是不可能的结果。

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}

A couple of tips:

1

A terminating \0 is implicit in any double quote string, and by adding an additional at the end you end up with two. The following two initializations are identical:

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

So

char drumReadString[] = "Hello";

is enough, and specifying the size of the array is optional when it is initialized like this, the compiler will figure out the required size (6 bytes).

2

When writing a string, you might just as well just write all characters in one go (instead of writing one by one character sizeOfString times):

fwrite(drumCString, sizeOfString, 1, fp);

3

Even though not so common for a normal desktop pc scenario, malloc can return NULL and you will benefit from developing a habbit of always checking the result because in embedded environments, getting NULL is not an unlikely outcome.

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}
风蛊 2024-09-01 02:42:35

你不写终止NUL,你不需要,但你必须在阅读时考虑添加它。即malloc stringLength + 1 char,读取stringLength chars并在读取的末尾添加\0

现在通常的警告:如果您按照此处的方式编写二进制文件,则有很多未声明的假设,这些假设使您的格式难以移植,有时甚至难以移植到同一编译器的另一个版本 - 我已经在编译器版本之间的结构变化。

You don't write the terminating NUL, you don't need to but then you have to think about adding it when reading. ie malloc stringLength + 1 char, read stringLength chars and add a \0 at the end of what has been read.

Now the usual warning: if you are writing binary file the way you are doing here, you have lots of unstated assumptions which make your format difficult to port, sometimes even to another version of the same compiler -- I've seen default alignment in struct changes between compiler versions.

半葬歌 2024-09-01 02:42:35

还有一些要添加到 paxdiablo 和 AProgrammer 中的内容 - 如果您将来打算使用 malloc,只需从一开始就这样做。这是更好的形式,意味着您在切换时无需进行调试。

另外,我没有完全看到 unsigned Short 的用法,如果您计划编写二进制文件,请考虑 unsigned char 类型通常大小为字节,这使得它非常方便用于此目的。

Some more to add to paxdiablo and AProgrammer - if you are going to use malloc in the future, just do it from the get go. It's better form and means you won't have to debug when switch over.

Additionally I'm not fully seeing the use of the unsigned short, if you are planning on writing a binary file, consider that the unsigned char type is generally of size byte, making it very convenient for that purpose.

不语却知心 2024-09-01 02:42:35

您只需在 fread 函数中删除 &drumReadString 即可。您只需在该函数中使用rumReadString,如 ganesh 提到的那样。因为,drumReadString 是一个数组。数组类似于直接指向内存位置的指针。

You Just remove your &drumReadString in the fread function.You simply use drumReadString in that function as ganesh mentioned.Because,drumReadString is an array.Array is similar to pointers which point to the memory location directly.

凌乱心跳 2024-09-01 02:42:34

你读书的时候做错了。
你已经把 &对于指针变量,这就是它给出分段错误的原因。

我删除了它工作正常并且正确返回 Hello 的信息。

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

You are doing wrong while reading.
you have put the & for the pointer variable that's why it gives segmentation fault.

I removed that it works fine and it returns Hello correctly.

int count = fread(drumReadString, sizeof(char), stringLength, fp);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文