【发布时间】:2021-05-30 06:46:07
【问题描述】:
我有两个源自 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 的转换过程,而正是这种转换,我需要它在不丢失数据的情况下生存。
【问题讨论】:
-
你为什么认为他们是valid characters?
-
如果
Encoding.Unicode.GetBytes无法获取它,那么它可能一开始就没有正确加载。 SQLite handles Unicode fine如何将这些字符串转换为 C#,请显示代码。 -
因为它们已经作为文件存在于操作系统中。我没有这样命名它们,它们已经这样存在了
-
为什么名字前面有个\?
-
它们是unicode字符,每个字符以\uxxxx的格式显示