在C ++中,将结构的每个成员写入文件并将结构对象直接写入文件有什么区别吗? [英] Is there any difference betwwen writing each and every member of struct to a file and writing structure object directly to a file in c++?

查看:78
本文介绍了在C ++中,将结构的每个成员写入文件并将结构对象直接写入文件有什么区别吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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是否相同?

In this example will both the example files be identical with data or different? Are instruction 1 and instruction 2 same?

推荐答案

有很大的不同.

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

Approach 1) writes the number using ASCII encoding, so there's an ASCII-encoded byte for each digit in the number. For example, the number 28 is encoded as one byte containing ASCII '2' (value 50 decimal, 32 hex) and another for '8' (56 / 0x38). If you look at the file in a program like less you'll be able to see the 2 and the 8 in there as human-readable text. Then << obj.abc writes the characters in abc up until (but excluding) the first NUL (0-value byte): if there's no NUL you run off the end of the buffer and have undefined behaviour: your program may or may not crash, it may print nothing or garbage, all bets are off. If your file is in text mode, it might translate any newline and/or carriage return characters in abc1 to some other standard representation of line breaks your operating system uses (e.g. it might automatically place a carriage return after every newline you write, or remove carriage returns that were in abc1).

方法2)将sizeof(obj)个字节写入内存:这是一个恒定数目的字节,无论其内容是什么.该数字将以二进制形式存储,因此less之类的程序不会向您显示num1中的人类可读数字.
根据CPU在内存中存储数字的方式,数字中的字节可能会以不同顺序存储在文件中(称为

Approach 2) writes the sizeof(obj) bytes in memory: that's a constant number of bytes regardless of their content. The number will be stored in binary, so a program like less won't show you the human-readable number from num1.
Depending on the way your CPU stores numbers in memory, you might have the bytes in the number stored in different orders in the file (something called endianness). There'll then always be 10 characters from abc1 even if there's a NUL in there somewhere. Writing out binary blocks like this is normally substantially faster than converting number to ASCII text and the computer having to worry about if/where there are NULs. Not that you normally have to care, but not all the bytes written necessarily contribute to the logical value of obj: some may be padding.

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

A more subtle difference is that for approach 1) there are ostensibly multiple object states that could produce the same output. Consider {123, "45"} and {12345, ""} -> either way you'd print "12345". So, you couldn't later open and read from the file and be sure to set num1 and abc to what they used to be. I say "ostensibly" above because you might happen to have some knowledge we don't, such as that the abc1 field will always start with a letter. Another problem is knowing where abc1 finishes, as its length can vary. If these issues are relevant to your actual use (e.g. abc1 could start with a digit), you could for example write << obj.num1 << ' ' << obj.abc1 << '\n' so the space and newline would tell you where the fields end (assuming abc1 won't contain newlines: if it could, consider another delimiter character or an escaping/quoting convention). With the space/newline delimiters, you can read the file back by changing the type of abc1 to std::string to protect against overruns by corrupt or tampered-with files, then using if (inputStream >> obj.num1 && getline(inputStream, obj.abc1)) ...process obj.... getline can cope with embedded spaces and will read until a newline.

示例:{258, "hello\0\0\0\0\0"}在sizeof(int)为32且结构填充为12个字节的小端系统上将打印(偏移量和字节值显示在

Example: {258, "hello\0\0\0\0\0"} on a little-endian system where sizeof(int) is 32 and the stucture's padded out to 12 bytes would print (offsets and byte values shown in hexadecimal):

              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). (搜索二进制编码"以了解有关此内容的更多信息.)

Notes: for approach 2, 00 00 01 02 encodes 100000010 binary which is 258 decimal. (Search for "binary encoding" to learn more about this).

这篇关于在C ++中,将结构的每个成员写入文件并将结构对象直接写入文件有什么区别吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆