您可以帮助我如何编码与特殊符号混合的非拉丁(俄语)字母,例如:
Abc Ø абв
(这里是英文文本,特殊符号“拉丁o”和俄语文本)。
我现有的 RTF 模板内含“占位符”文本,我需要的是将这个“占位符”替换为“Abc Ø абв”:
我使用页面底部此处的函数将UTF-8解码为Win-1251 - 它成功写入俄语字母,但最终我得到“Ш”而不是“Ø”:
这是我的示例代码以及输入和输出文件:
输入rtf:https://mega.nz/file/CtNB2CiY#yid1nLq9P6Jo8zSRAsXeGai-mZLV6xP1OvN1jDpFyG4
由以下代码生成的输出rtf:https://mega.nz/file/asMExKJI#q8oRn1J9oWMlUck6tJ6MdpVGiIjt81kNFRo7T3eSBTU
const http = require('http');
const port = 3100;
function utf8_decode_to_win1251(srcStr) {
var tgtStr = "",
c = 0;
for (var i = 0; i < srcStr.length; i++) {
c = srcStr.charCodeAt(i);
if (c > 127) {
if (c > 1024) {
if (c === 1025) {
c = 1016;
} else if (c === 1105) {
c = 1032;
}
c -= 848;
}
// c = c % 256; // ???
}
tgtStr += String.fromCharCode(c);
}
return tgtStr;
}
const server = http.createServer(function (req, res) {
const fs = require('fs');
// read existing file
fs.readFile("C:\input.rtf", "utf8", (err, inputText) => {
if (err) {
console.error(err);
return;
}
// I want to replace 'placeholder' text in file with this test text:
let text = `Abc Ø абв`; // 'Abc Ø абв'
text = utf8_decode_to_win1251(text); // text with encoded russian letters 'Abc Ø àáâ'
// replace placeholder from input RTF with text with non-latin characters 'Abc Ø àáâ':
inputText = inputText.replace("placeholder", text);
// RTF uses 8-bit so need to convert from unicode
let buf = Buffer.from(inputText, "ascii"); // "binary" also gives wrong output text https://stackoverflow.com/a/34476862/348736
// write output file to disk
fs.writeFile("C:\output.rtf", buf, function (error, resultFile) { // result file contains 'Abc Ш абв', which is wrong..
if (!error) {
console.info('Created file', resultFile);
}
else {
console.error(error);
}
});
});
});
server.listen(port, function (error) {
if (error) {
console.log(`${error}`);
} else {
console.log(`listening on port ${port}`);
}
})
我认为你不能用 8 位编码来表示“Abc Ø абв”。至少据我所知。
我试图理解你的代码中发生了什么。问题是,在 Windows-1251 中没有字符 Ø,您可以在此表中查看https://www.ascii-code.com/CP1251。在 Windows-1251 中,字符 aбв 确实存在。因此,该函数实际生成 Windows-1251 是没有意义的。但是如果你尝试将“Abc Ø абв”转换为Windows-1252,你会发现Windows-1252确实有字符Ø,但没有абв(这里的a是西里尔字母a,与拉丁字母不同) A)。我认为发生的情况是,您解码为 Windows-1252,但数据最终到达了应该是 Windows-1251 的某个位置。
通过以下方式播放: “Abc Ø абв”翻译为十六进制 (utf-8)
41 62 63 C3 98 D0 B0 D0 B1 D0 B2
。尝试将其解码为 Windows-1252 会得到 41 62 63 D8 E0 E1 E2
。
打印出“Abc Ø àáâ”,这正是您所得到的。
如果随后将同一十六进制的编码从 Windows-1252 更改为 Windows-1251,则会打印“Abc Ш абв”。这又是你的例子中发生的事情。
(您可以在这里尝试一下https://www.rapidtables.com/convert/number/hex-to-ascii.html)。