将 Unicode 的 UTF8 表示写入文件
Write UTF8 representation of Unicode to file
我有一个专有文件(数据库)格式,我目前正在尝试将其迁移到 SQL 数据库。因此,我将文件转换为 sql 转储,这已经可以正常工作了。现在剩下的唯一问题是他们处理不在 32 到 126 的 ASCII 十进制范围内的字符的怪异方式。他们有一个以 Unicode(十六进制 - 例如 20AC = €)存储的所有这些字符的集合,由他们自己的索引内部索引。
我现在的计划是:我想创建一个 table 来存储内部索引、unicode(十六进制)和字符表示 (UTF-8)。此 table 可用于以后的更新。
现在问题来了:如何将 unicode 十六进制值的 UTF-8 字符表示形式写入文件?当前代码如下所示:
this->outFile.open(fileName + ".sql", std::ofstream::app);
std::string protyp;
this->inFile.ignore(2); // Ignore the ID = 01.
std::getline(this->inFile, protyp); // Get the PROTYP Identifier (e.g. 1)
protyp = "\" + protyp;
std::string unicodeHex;
this->inFile.ignore(2); // Ignore the ID = 01.
std::getline(this->inFile, unicodeHex); // Get the Unicode HEX Identifier (e.g. 002C)
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
const std::wstring wide_string = this->s2ws("\u" + unicodeHex);
const std::string utf8_rep = converter.to_bytes(wide_string);
std::string valueString = "('" + protyp + "', '" + unicodeHex + "', '" + utf8_rep + "')";
this->outFile << valueString << std::endl;
this->outFile.close();
但这只是打印出这样的东西:
('1', '002C', '\u002C'),
虽然所需的输出是:
('1', '002C', ','),
我做错了什么?我不得不承认,当涉及到字符编码和其他东西时,我不是那么确定:/。我正在研究 Windows 7 64 位,如果它有什么不同的话。
提前致谢。
正如@Mark Ransom 在评论中指出的那样,我最好的选择是将十六进制字符串转换为整数并使用它。
这就是我所做的:
unsigned int decimalHex = std::stoul(unicodeHex, nullptr, 16);;
std::string valueString = "('" + protyp + "', '" + unicodeHex + "', '" + this->UnicodeToUTF8(decimalHex) + "')";
虽然 UnicodeToUTF8 的函数取自此处 Unsigned integer as UTF-8 value
std::string UnicodeToUTF8(unsigned int codepoint)
{
std::string out;
if (codepoint <= 0x7f)
out.append(1, static_cast<char>(codepoint));
else if (codepoint <= 0x7ff)
{
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else if (codepoint <= 0xffff)
{
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else
{
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
return out;
}
我有一个专有文件(数据库)格式,我目前正在尝试将其迁移到 SQL 数据库。因此,我将文件转换为 sql 转储,这已经可以正常工作了。现在剩下的唯一问题是他们处理不在 32 到 126 的 ASCII 十进制范围内的字符的怪异方式。他们有一个以 Unicode(十六进制 - 例如 20AC = €)存储的所有这些字符的集合,由他们自己的索引内部索引。
我现在的计划是:我想创建一个 table 来存储内部索引、unicode(十六进制)和字符表示 (UTF-8)。此 table 可用于以后的更新。
现在问题来了:如何将 unicode 十六进制值的 UTF-8 字符表示形式写入文件?当前代码如下所示:
this->outFile.open(fileName + ".sql", std::ofstream::app);
std::string protyp;
this->inFile.ignore(2); // Ignore the ID = 01.
std::getline(this->inFile, protyp); // Get the PROTYP Identifier (e.g. 1)
protyp = "\" + protyp;
std::string unicodeHex;
this->inFile.ignore(2); // Ignore the ID = 01.
std::getline(this->inFile, unicodeHex); // Get the Unicode HEX Identifier (e.g. 002C)
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
const std::wstring wide_string = this->s2ws("\u" + unicodeHex);
const std::string utf8_rep = converter.to_bytes(wide_string);
std::string valueString = "('" + protyp + "', '" + unicodeHex + "', '" + utf8_rep + "')";
this->outFile << valueString << std::endl;
this->outFile.close();
但这只是打印出这样的东西:
('1', '002C', '\u002C'),
虽然所需的输出是:
('1', '002C', ','),
我做错了什么?我不得不承认,当涉及到字符编码和其他东西时,我不是那么确定:/。我正在研究 Windows 7 64 位,如果它有什么不同的话。 提前致谢。
正如@Mark Ransom 在评论中指出的那样,我最好的选择是将十六进制字符串转换为整数并使用它。 这就是我所做的:
unsigned int decimalHex = std::stoul(unicodeHex, nullptr, 16);;
std::string valueString = "('" + protyp + "', '" + unicodeHex + "', '" + this->UnicodeToUTF8(decimalHex) + "')";
虽然 UnicodeToUTF8 的函数取自此处 Unsigned integer as UTF-8 value
std::string UnicodeToUTF8(unsigned int codepoint)
{
std::string out;
if (codepoint <= 0x7f)
out.append(1, static_cast<char>(codepoint));
else if (codepoint <= 0x7ff)
{
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else if (codepoint <= 0xffff)
{
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else
{
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
return out;
}