将十六进制数据输出到文件的正确方法是什么?

发布于 2024-11-15 02:25:26 字数 644 浏览 3 评论 0原文

我读过有关 [ostream] <<十六进制 << 0x[十六进制值],但我对此有一些疑问

(1)我使用output.open将我的文件流output定义为十六进制输出文件流("BWhite.bmp",ios::binary);,既然我这样做了,这是否会使 output<< 操作中的 hex 参数多余的?

(2) 如果我有一个整数值,我想存储在文件中,我使用了这个:

int i = 0;
output << i;

我会存储在小端还是大端? endi-ness 会根据程序执行或编译的计算机而变化吗?

该值的大小是否取决于运行它的计算机?我需要使用十六进制参数吗?

(3) 有没有办法将原始十六进制数字输出到文件中?如果我希望文件具有十六进制数字 43,我应该使用什么?

输出<< 0x43输出<<十六进制 << 0x43 都输出 ASCII 4,然后输出 ASCII 3。

输出这些十六进制数字的目的是为 .bmp 文件制作标题。

I've read about [ostream] << hex << 0x[hex value], but I have some questions about it

(1) I defined my file stream, output, to be a hex output file stream, using output.open("BWhite.bmp",ios::binary);, since I did that, does that make the hex parameter in the output<< operation redundant?

(2)
If I have an integer value I wanted to store in the file, and I used this:

int i = 0;
output << i;

would i be stored in little endian or big endian? Will the endi-ness change based on which computer the program is executed or compiled on?

Does the size of this value depend on the computer it's run on? Would I need to use the hex parameter?

(3) Is there a way to output raw hex digits to a file? If I want the file to have the hex digit 43, what should I use?

output << 0x43 and output << hex << 0x43 both output ASCII 4, then ASCII 3.

The purpose of outputting these hex digits is to make the header for a .bmp file.

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

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

发布评论

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

评论(3

灰色世界里的红玫瑰 2024-11-22 02:25:26

格式化输出运算符 << 的作用就是:格式化输出。是给弦用的。

因此,std::hex 流操纵器告诉流将数字输出为十六进制格式的字符串。

如果您想输出原始二进制数据,请使用未格式化的输出函数,例如basic_ostream::putbasic_ostream::write

您可以输出这样的 int:

int n = 42;
output.write(&n, sizeof(int));

此输出的字节顺序将取决于体系结构。如果您希望有更多的控制权,我建议如下:

int32_t n = 42;
char data[4];
data[0] = static_cast<char>(n & 0xFF);
data[1] = static_cast<char>((n >> 8) & 0xFF);
data[2] = static_cast<char>((n >> 16) & 0xFF);
data[3] = static_cast<char>((n >> 24) & 0xFF);
output.write(data, 4);

此示例将输出一个 32 位整数作为小端字节序,无论平台的字节序如何。不过,如果 char 已签名,请小心将其转换回来。

The formatted output operator << is for just that: formatted output. It's for strings.

As such, the std::hex stream manipulator tells streams to output numbers as strings formatted as hex.

If you want to output raw binary data, use the unformatted output functions only, e.g. basic_ostream::put and basic_ostream::write.

You could output an int like this:

int n = 42;
output.write(&n, sizeof(int));

The endianness of this output will depend on the architecture. If you wish to have more control, I suggest the following:

int32_t n = 42;
char data[4];
data[0] = static_cast<char>(n & 0xFF);
data[1] = static_cast<char>((n >> 8) & 0xFF);
data[2] = static_cast<char>((n >> 16) & 0xFF);
data[3] = static_cast<char>((n >> 24) & 0xFF);
output.write(data, 4);

This sample will output a 32 bit integer as little-endian regardless of the endianness of the platform. Be careful converting that back if char is signed, though.

娇纵 2024-11-22 02:25:26

你说

“有没有办法将原始十六进制数字输出到文件中?如果我希望文件具有十六进制数字 43,我应该使用什么?”

“原始十六进制数字”将取决于您对位集合所做的解释。考虑以下情况:

 Binary  :    0 1 0 0 1 0 1 0
 Hex     :    4 A
 Octal   :    1 1 2
 Decimal :    7 4
 ASCII   :    J

以上所有内容都代表相同的数字量,但我们对它的解释不同。

因此,您只需将数据存储为二进制格式,即由数字表示的确切位模式。

EDIT1

当您以文本模式打开文件并在其中写入一个数字时,例如您写入 74 (如上例所示),它将被存储为两个 ASCII 字符 <代码>'7' 和 '4' 。为了避免这种情况,以二进制模式 ios::binary 打开文件并使用 write () 写入它。检查 http://courses.cs.vt.edu/~cs2604/ fall00/binio.html#write

You say

"Is there a way to output raw hex digits to a file? If I want the file to have the hex digit 43, what should I use? "

"Raw hex digits" will depend on the interpretation you do on a collection of bits. Consider the following:

 Binary  :    0 1 0 0 1 0 1 0
 Hex     :    4 A
 Octal   :    1 1 2
 Decimal :    7 4
 ASCII   :    J

All the above represents the same numeric quantity, but we interpret it differently.

So you can simply need to store the data as binary format, that is the exact bit pattern which is represent by the number.

EDIT1

When you open a file in text mode and write a number in it, say when you write 74 (as in above example) it will be stored as two ASCII character '7' and '4' . To avoid this open the file in binary mode ios::binary and write it with write () . Check http://courses.cs.vt.edu/~cs2604/fall00/binio.html#write

爱本泡沫多脆弱 2024-11-22 02:25:26

输出这些十六进制数字的目的是为.bmp 文件制作标题。

您似乎对文件的工作方式有很大的误解

流运算符 << 生成文本(人类可读的输出)。 .bmp 文件格式是一种人类无法读取的二进制格式(可以,但它不太好,如果没有工具我不会读取它)。

您真正想要做的是生成二进制输出并将其放置到文件中:

char   x = 0x43;
output.write(&x, sizeof(x));

这会将十六进制值 0x43 的一个字节数据写入输出流。这就是您想要的二进制表示形式。

我会以小端还是大端存储? endi-ness 会根据程序执行或编译的计算机而变化吗?

两者都不;您再次输出文本(不是二进制数据)。

int i = 0;
output.write(reinterpret_cast<char*>(&i), sizeof(i)); // Writes the binary representation of i

在这里,您确实需要担心整数值的字节顺序(和大小),这将根据您运行应用程序的硬件而有所不同。对于值 0,不必担心字节顺序,但您应该担心整数的大小。

我会将一些断言添加到我的代码中,以验证架构对于代码来说是否正确。然后让人们担心他们的架构是否不符合要求:

int test = 0x12345678;
assert((sizeof(test) * CHAR_BITS == 32) && "BMP uses 32 byte ints");
assert((((char*)&test)[0] == 0x78) && "BMP uses little endian");

有一系列函数可以帮助您处理字节顺序和大小。

http://www.gnu.org/s/hello/manual /libc/Byte-Order.html

函数:uint32_t htonl (uint32_t hostlong)
该函数将 uint32_t 整数 hostlong 从主机字节顺序转换为网络字节顺序。

// Writing to a file
uint32_t hostValue = 0x12345678;
uint32_t network   = htonl(hostValue);
output.write(&network, sizeof(network));

// Reading from a file
uint32_t network;
output.read(&network, sizeof(network);
uint32_t hostValue = ntohl(network);    // convert back to platform specific value.

// Unfortunately the BMP was written with intel in-mind
// and thus all integers are in liitle-endian.
// network bye order (as used by htonl() and family) is big endian.
// So this may not be much us to you.

最后一件事。当您以二进制格式打开文件 output.open("BWhite.bmp",ios::binary) 时,除了处理行尾序列的方式之外,它不会执行任何流式传输操作代码>.当文件为二进制格式时,输出不会被修改(您放入流中的内容就是写入文件的内容)。如果将流保留在文本模式下,则“\n”字符将转换为行尾序列(定义行尾的操作系统特定字符集)。由于您正在编写二进制文件,您绝对不希望您编写的字符受到任何干扰,因此二进制是正确的格式。但它不会影响您在流上执行的任何其他操作。

The purpose of outputting these hex digits is to make the header for a .bmp file.

You seem to have a large misconception of how files work.

The stream operators << generate text (human readable output). The .bmp file format is a binary format that is not human readable (will it is but its not nice and I would not read it without tools).

What you really want to do is generate binary output and place it the file:

char   x = 0x43;
output.write(&x, sizeof(x));

This will write one byte of data with the hex value 0x43 to the output stream. This is the binary representation you want.

would i be stored in little endian or big endian? Will the endi-ness change based on which computer the program is executed or compiled on?

Neither; you are again outputting text (not binary data).

int i = 0;
output.write(reinterpret_cast<char*>(&i), sizeof(i)); // Writes the binary representation of i

Here you do need to worry about endianess (and size) of the integer value and this will vary depending on the hardware that you run your application on. For the value 0 there is not much tow worry about endianess but you should worry about the size of the integer.

I would stick some asserts into my code to validate the architecture is OK for the code. Then let people worry about if their architecture does not match the requirements:

int test = 0x12345678;
assert((sizeof(test) * CHAR_BITS == 32) && "BMP uses 32 byte ints");
assert((((char*)&test)[0] == 0x78) && "BMP uses little endian");

There is a family of functions that will help you with endianess and size.

http://www.gnu.org/s/hello/manual/libc/Byte-Order.html

Function: uint32_t htonl (uint32_t hostlong)
This function converts the uint32_t integer hostlong from host byte order to network byte order.

// Writing to a file
uint32_t hostValue = 0x12345678;
uint32_t network   = htonl(hostValue);
output.write(&network, sizeof(network));

// Reading from a file
uint32_t network;
output.read(&network, sizeof(network);
uint32_t hostValue = ntohl(network);    // convert back to platform specific value.

// Unfortunately the BMP was written with intel in-mind
// and thus all integers are in liitle-endian.
// network bye order (as used by htonl() and family) is big endian.
// So this may not be much us to you.

Last thing. When you open a file in binary format output.open("BWhite.bmp",ios::binary) it does nothing to stream apart from how it treats the end of line sequence. When the file is in binary format the output is not modified (what you put in the stream is what is written to the file). If you leave the stream in text mode then '\n' characters are converted to the end of line sequence (OS specific set of characters that define the end of line). Since you are writing a binary file you definitely do not want any interference in the characters you write so binary is the correct format. But it does not affect any other operation that you perform on the stream.

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