c# - C# utf 字符串转换,无法正确显示的字符被转换为“未知字符” - 如何防止这种情况?
问题描述
我有两个从 Windows 文件名派生的字符串,其中包含在 Windows 中无法正确显示的 unicode 字符(它们只显示方框“未知字符”而不是正确的字符)。但是文件名是有效的,并且这些文件在操作系统中没有问题存在,这意味着我需要能够正确准确地处理它们。
我以通常的方式加载文件名:
string path = @"c:\folder";
foreach (FileInfo file in DirectoryInfo.EnumerateFiles(path))
{
string filename = file.FullName;
}
但为了解释这个问题,这些是我遇到问题的两个文件名:
string filename1 = "\ude18.txt";
string filename2 = "\udca6.txt";
两个字符串,两个文件名,一个 unicode 字符加上一个扩展名,两者都不同。到目前为止这很好,我可以毫无问题地读取和写入这些文件,但是我需要将这些字符串存储在 sqlite db 中,然后再检索它们。我所做的每一次尝试都会导致这两个字符都被更改为“未知字符”,因此原始数据丢失了,我无法再区分这两个字符串。起初我认为这是一个 sqlite 问题,并且我确保我的数据库是 UTF16 格式的,但事实证明是 c# 到 UTF16 的转换导致了问题。
如果我完全忽略 sqlite,只是尝试手动将这些字符串转换为 UTF16(或任何其他编码),这些字符将转换为“未知字符”并且原始数据会丢失。如果我这样做:
System.Text.Encoding enc = System.Text.Encoding.Unicode;
string filename1 = "\ude18.txt";
string filename2 = "\udca6.txt";
byte[] name1Bytes = enc.GetBytes(filename1);
byte[] name2Bytes = enc.GetBytes(filename2);
然后我检查字节数组'name1Bytes'和'name2Bytes'它们都是相同的。我可以看到这两种情况下的 unicode 字符都已转换为一对字节 253 和 255 - 未知字符。果然当我转换回来
string newFilename1 = enc.GetString(name1Bytes);
string newFilename2 = enc.GetString(name2Bytes);
每种情况下的原始 unicode 字符都会丢失,并替换为菱形问号符号。我完全丢失了原始文件名。
似乎这些编码转换依赖于能够显示字符的系统字体,这是一个问题,因为这些字符串已经作为文件名存在,并且无法更改文件名。在将这些数据发送到 sqlite 时,我需要以某种方式保存这些数据,当它发送到 sqlite 时,它会经历一个到 UTF16 的转换过程,而正是这种转换,我需要它在不丢失数据的情况下生存下来。
解决方案
如果将 achar
转换为 a int
,则会绕过 Unicode 转换机制获得数值:
foreach (char ch in filename1)
{
int i = ch; // 0x0000de18 == 56856 for the first char in filename1
... do whatever, e.g., create an int array, store it as base64
}
事实证明这也有效,并且可能更优雅:
foreach (int ch in filename1)
{
...
}
所以也许是这样的:
string Encode(string raw)
{
byte[] bytes = new byte[2 * raw.Length];
int i = 0;
foreach (int ch in raw)
{
bytes[i++] = (byte)(ch & 0xff);
bytes[i++] = (byte)(ch >> 8);
}
return Convert.ToBase64String(bytes);
}
string Decode(string encoded)
{
byte[] bytes = Convert.FromBase64String(encoded);
char[] chars = new char[bytes.Length / 2];
for (int i = 0; i < chars.Length; ++i)
{
chars[i] = (char)(bytes[i * 2] | (bytes[i * 2 + 1] << 8));
}
return new string(chars);
}
推荐阅读
- java - Eclipse android项目 - 无法导入库
- python - 是否可以从第一类以下的类继承?Python
- javascript - 启用 interactivityEnabled 选项时 CanvasJS 图表停止网页
- visual-studio - 更改警告颜色:ENC1003 在应用程序运行时不会应用在项目中所做的更改
- python - 在 Selenium Phython 中出现错误:“此版本的 ChromeDriver 仅支持 Chrome 版本 79”
- google-sheets - 将行与数组公式查询组合时如何删除空格?
- asp.net - 多部分标识符“我的电子邮件”无法绑定
- c# - 如何切换布尔状态?
- c# - 当 DroppedDown=true 时,C# Windows 窗体 ComboBox DropDown 不突出显示所选项目
- java - Java中的整数是否必须初始化?