[英]Writing std::string with non-ascii data to file
以下是我的问题的简化示例。 我有一些外部字节数据,它看起来像是带有cp1252编码度符号0xb0
的字符串。 当它以std::string
形式存储在我的程序中时,它正确地表示为0xffffffb0
。 但是,当将该字符串写入文件时,生成的文件只有一个字节长,只有0xb0
。 如何将字符串写入文件? UTF-8
的概念如何融入其中?
#include <iostream>
#include <fstream>
typedef struct
{
char n[40];
} mystruct;
static void dump(const std::string& name)
{
std::cout << "It is '" << name << "'" << std::endl;
const char *p = name.data();
for (size_t i=0; i<name.size(); i++)
{
printf("0x%02x ", p[i]);
}
std::cout << std::endl;
}
int main()
{
const unsigned char raw_bytes[] = { 0xb0, 0x00};
mystruct foo;
foo = *(mystruct *)raw_bytes;
std::string name = std::string(foo.n);
dump(name);
std::ofstream my_out("/tmp/out.bin", std::ios::out | std::ios::binary);
my_out << name;
my_out.close();
return 0;
}
运行上面的程序会在STDOUT上产生以下内容
It is '�'
0xffffffb0
首先,这是必须阅读的内容:
每个软件开发人员绝对,肯定必须绝对了解Unicode和字符集(无借口!)
现在,完成此操作后,您必须了解什么类型表示p[i]
。
它是char
,在C中是带sign
的小整数值! char
可以为负!
现在,由于您具有cp1252
字符,因此它们不在ASCII范围内。 这意味着这些字符被视为负值!
现在,当它们转换为int
,将复制符号位,并且在尝试打印它时,您将看到0xffffff<actual byte value>
。
要在C
处理该问题,首先应将其转换为unsigned char
:
printf("0x%02x ", (unsigned char)p[i]);
那么默认转换将用零填充缺失的位,而printf()
将为您提供适当的值。
现在,在C ++中,这有点麻烦,因为流运算符将char
和unsigned char
视为字符表示。 因此,以十六进制方式打印它们,应该是这样的:
int charToInt(char ch)
{
return static_cast<int>(static_cast<unsigned char>(ch));
}
std::cout << std::hex << charToInt(s[i]);
现在,从char
直接转换为unsigned int
不会解决此问题,因为编译器将默默地先与int
进行对话。
看到这里: https : //wandbox.org/permlink/sRmh8hZd78Oar7nF
UTF-8与该问题无关。
离题:请在编写纯C ++代码时不要使用C
它是没有意义的,它使代码更难维护,而且速度也不快。 所以:
char*
或char[]
存储字符串。 只需使用std::string
。 printf()
,请使用std::cout
(或者fmt
库,如果您喜欢格式字符串,它将成为将来的C ++标准)。 alloc()
, malloc()
, free()
-在现代C ++中,请使用std::make_unique()
和std::make_shared()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.