繁体   English   中英

将带有非ascii数据的std :: string写入文件

[英]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 ++中,这有点麻烦,因为流运算符将charunsigned 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM