我试图在Image上写入某些字节,例如:
“་。༉ᵒᵗᵗ͟ᵋༀ͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟.......”
当我在图像上显示它时,我得到以下内容......
图像:
我尝试更改字符串的编码类型,当我收到字节并且没有设置字体但我尝试了所有默认的Microsoft字体以及我在Internet上找到的一些自定义字体。我究竟做错了什么?
修改:原作正在使用Graphics.DrawString
。我尝试了TextRenderer
,结果几乎相同。
图像:
这是我用来生成图片的代码:
string text = "[rotten4pple] །༉ᵒᵗᵗ͟ᵋༀ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟. . .";
var font = new Font("Arial", 8, FontStyle.Regular);
var bitmap = new Bitmap(1, 1);
var size = Graphics.FromImage(bitmap).MeasureString(text, font);
bitmap = new Bitmap((int)size.Width + 4, (int)size.Height + 4);
using (var gfx = Graphics.FromImage(bitmap))
{
gfx.Clear(Color.White);
TextRenderer.DrawText(gfx, cmd.AllArguments, font, new Point(2, 2),
Color.Black, Color.White);
}
变量cmd.AllArguments
传递给方法,我相信字符串是使用windows-1252
编码的。
答案 0 :(得分:3)
不要将Graphics.DrawString
用于unicode字符。
您应该迁移到TextRenderer.DrawText
,例如:
TextRenderer.DrawText(e.Graphics, "こんにちは", this.Font,
new Point(10, 10), this.ForeColor, this.BackColor, flags);
缺点是您无法指定Brush
。
我测试了它。我认为其他一些必须继续下去,因为它似乎对我有用。这是我的代码:
private void Form1_Paint(object sender, PaintEventArgs e)
{
var text = " །༉ᵒᵗᵗ͟ᵋༀ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟ ͟. . . ";
TextRenderer.DrawText(e.Graphics, "TextRenderer.DrawText" + text , this.Font,
new Point(10, 10), this.ForeColor, this.BackColor);
e.Graphics.DrawString("Graphics.DrawString" + text, this.Font,
new SolidBrush(this.ForeColor), new PointF(10, 30));
}
注意:字体为Arial Unicode MS 8.25pt
。
输出:
这是原始字符串,以UTF-8存储:
[rotten4pple]་。༉ᵒᵗᵗ͟ᵋༀ͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟͟。 。
这是你得到的错误的字符串,存储在Windows-1252中:
[rotten4pple]à¼à¼‰áμ'áμ-áμ-ÍŸáμ<Í€ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 。
他们是二元相等的。这是两个字符串的字节的十六进制表示:
5B 72 6F 74 74 65 6E 34 70 70 6C 65 5D 20 E0 BC
8D E0 BC 89 E1 B5 92 E1 B5 97 E1 B5 97 CD 9F E1
B5 8B E0 BC 80 EF A3 BF 20 F0 9F 90 A2 20 CD 9F
20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F F0
9F 90 A2 20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F 20
CD 9F 20 CD 9F 20 CD 9F F0 9F 90 9B 20 CD 9F 20
CD 9F 20 CD 9F 20 CD 9F 20 CD 9F 20 CD 9F F0 9F
90 A2 2E 20 2E 20 2E
由于这是对二进制值的重新解释而不是重新编码,因此在.NET中使用Encoding.Convert
从一个转换为另一个是不可行的。相反,您应该以错误的编码获取字符串的二进制表示,并直接将其读作正确的编码:
var text = cmd.AllArguments;
var bytes = Encoding.GetEncoding(1252).GetBytes(text);
text = Encoding.UTF8.GetString(bytes);
备注强>
您一直在询问默认情况下使用您使用的API的编码。我不熟悉您正在使用的API ......但是,它有可能取决于机器的配置。您应该查找允许您指定接收UTF-8字符串的重载。
您实际上可能正在接收byte[]
,因此您可以直接使用Encoding.UTF8.GetString
。如果您无法指定编码,则应考虑切换为发送byte[]
,而目的是更好地控制编码。
在这方面,请不要使用Encoding.Default
,因为它将是机器语言的扩展ASCII。
顺便说一句,UTF-8是网络的不错选择,不仅因为它独立于语言和其他区域配置,还因为它独立于字节顺序(字节顺序)。