首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在c++中将结构体的每个成员写入文件和将结构对象直接写入文件之间有什么区别吗?

在c++中将结构体的每个成员写入文件和将结构对象直接写入文件之间有什么区别吗?
EN

Stack Overflow用户
提问于 2018-04-21 11:58:01
回答 1查看 95关注 0票数 3
代码语言:javascript
复制
#include <iostream>
#include <fstream>
using namespace std;
struct example
{
 int num1;
 char abc[10];
}obj;

int main () 
{
 ofstream myfile1 , myfile2;
 myfile1.open ("example1.txt");
 myfile2.open ("example2.txt");
 myfile1 << obj.num1<<obj.abc;  //instruction 1
 myfile2.write((char*)&obj, sizeof(obj)); //instruction 2
 myfile1.close();
 myfile2.close();
 return 0;
}

在本例中,两个示例文件是否与数据相同或不同?指令1和指令2相同吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-21 12:12:04

有很大的不同。

方法1)使用ASCII编码写入数字,因此该数字中的每个数字都有一个ASCII编码的字节。例如,数字28被编码为一个字节,包含ASCII '2‘(值50小数点,32十六进制),另一个字节包含'8’(56 / 0x38)。如果您查看像less这样的程序中的文件,您将能够看到其中的2和8作为人类可读的文本。然后<< obj.abcabc中写入字符,直到(但不包括)第一个NUL (0-值字节):如果没有NUL,则在缓冲区的末端运行并具有未定义的行为:您的程序可能会崩溃,也可能不会崩溃,它可能不会打印任何东西或垃圾,所有的赌注都会被关闭。如果您的文件处于文本模式,它可能会将abc1中的任何换行符和/或回车字符转换为操作系统使用的中断行的其他标准表示形式(例如,它可能会在您编写的每一行换行符之后自动放置一个回车,或者删除abc1中的回车)。

方法2)在内存中写入sizeof(obj)字节:这是一个恒定的字节数,而不管其内容如何。数字将被存储在二进制文件中,所以像less这样的程序不会显示来自num1的人类可读的数字。

根据CPU在内存中存储数字的方式,您可能会在文件中以不同的顺序存储数字中的字节(称为https://en.wikipedia.org/wiki/Endianness)。然后,即使在某个地方有一个abc1,也总会有10个字符来自NUL。写出这样的二进制块通常比将数字转换为ASCII文本和计算机必须担心是否存在NUL的速度要快得多。并不是说您通常需要关心,但并不是所有写入的字节都必然有助于obj的逻辑值:有些可能是填充

一个更微妙的区别是,对于方法1)表面上有多个对象状态可以产生相同的输出。考虑一下{123, "45"}{12345, ""} ->这两种打印"12345“的方式。因此,您以后无法打开和读取文件,并确保将num1abc设置为以前的样子。我在上面说“表面上的”是因为您可能碰巧有一些我们不知道的知识,例如abc1字段总是以字母开头。另一个问题是知道abc1在哪里结束,因为它的长度可能会有所不同。如果这些问题与实际使用相关(例如,abc1可以以数字开头),则可以编写<< obj.num1 << ' ' << obj.abc1 << '\n',这样空格和换行符就可以告诉您字段的结尾位置(假设abc1不包含换行符:如果可以,可以考虑另一个分隔符字符或逃逸/quoting约定)。使用空格/换行符,您可以通过将abc1类型更改为std::string来读取文件,以防止损坏或篡改的文件溢出,然后使用if (inputStream >> obj.num1 && getline(inputStream, obj.abc1)) ...process obj...getline可以处理嵌入的空格,并会一直读到换行符。

例如:在一个小端系统上的{258, "hello\0\0\0\0\0"},其中sizeof(int)为32,结构的填充为12字节将打印出来(十六进制中显示的偏移和字节值):

代码语言:javascript
复制
              bytes in file at offset...
              00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f

approach 1)   32  35  38  69  65  6c  6c  6f
              '2' '5' '8' 'h' 'e' 'l' 'l' 'o'

approach 2)   00  00  01  02  69  65  6c  6c  6f  00  00  00  00  00  00  00
              [-32 bit 258-]  'h' 'e' 'l' 'l' 'o''\0''\0''\0''\0''\0' pad pad

注意:对于方法2,00 00 01 02编码的100000010二进制数为258个小数点。(搜索“二进制编码”以了解更多相关信息)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49955515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档