使用Unicode字符读取文件

12

我有一个asp.net c#页面,正在尝试读取一个包含以下字符的文件 ’,并将其转换为' (从倾斜的撇号到撇号)。

FileInfo fileinfo = new FileInfo(FileLocation);
string content = File.ReadAllText(fileinfo.FullName);

//strip out bad characters
content = content.Replace("’", "'");

这不起作用,并且将倾斜的撇号变成了问号标记。


你说它把倾斜的字符变成了“?”。这意味着你 Replace 函数的第一个参数是正确的,但第二个参数是错误的。它可能是一个看起来像单引号的 Unicode 字符,但实际上不是单引号。在没有 Unicode 字体的显示器上或者打印到屏幕时,无法识别的 Unicode 字符会显示为“?”。 - Stephen Chung
检查第二个参数是否为正确的字符。您可能意外打开了亚洲输入法或其他输入法,并键入了一个看起来与屏幕上的简单引号完全相同的亚洲引号字符(Unicode)。有时很难区分它们的不同。 - Stephen Chung
是的,这与文件的读取有关。我使用了以下代码:string content = File.ReadAllText(fileinfo.FullName, Encoding.Default); 它成功地读取了文件内容。谢谢! - chris
4个回答

15

我怀疑问题并不在于替换,而是在于读取文件本身。我以前尝试过一种简单粗暴的方法(使用Word和复制粘贴),结果也和您一样得到了相同的结果,但检查 content 后发现 .Net 框架认为该字符是 Unicode 字符 65533,即在字符串替换之前的“WTF?”字符。您可以通过检查 Visual Studio 调试器中的相关字符来验证这一点,它应该显示字符代码:

content[0]; // 65533 '�'

replace方法无法正常工作的原因很简单 - content 不包含您提供的字符串:

content.IndexOf("’"); // -1

如果文件读取不正常,可能是因为在读取文件时使用了错误的编码方式。(如果未指定编码,则 .Net 框架将尝试为您确定正确的编码方式,但没有 100% 可靠的方法可以做到这一点,因此往往会出现错误)。您需要使用的确切编码方式取决于文件本身,但在我的情况下使用的编码方式是Extended ASCII,因此我只需要指定正确的编码方式即可读取该文件:

string content = File.ReadAllText(fileinfo.FullName, Encoding.GetEncoding("iso-8859-1"));

(请参考这个问题。)

当在代码中使用“奇怪”的字符时,您需要确保在替换字符串中指定正确的字符 - 您可以通过字符编码而不是字符串字面量来指定字符,这样可能更可靠(如果源文件的编码发生变化,则字符串字面量可能会导致问题)。例如,以下内容对我有效:

content = content.Replace("\u0092", "'");

2
与其使用(char)146,使用'\u0092'可能更易读,因为它与字符代码表匹配。 - Jeffrey L Whitledge
'\u0092' == (char)146 的原因是 \u 表示法使用十六进制,而 0x92 == 146 - Justin

3
我猜这个文件是用Windows-1252编码的。这几乎与ISO 8859-1相同。不同之处在于,Windows-1252使用“可显示字符”而不是0x80到0x9F范围内的控制字符。(这就是倾斜的撇号所在的位置。即0x92)
//Specify Windows-1252 here
string content = File.ReadAllText(fileinfo.FullName, Encoding.GetEncoding(1252));
//Your replace code will then work as is
content = content.Replace("’", "'");

Encoding.GetEncoding("Windows-1252") - Daniel

2
// This should replace smart single quotes with a straight single quote

Regex.Replace(content, @"(\u2018|\u2019)", "'");

//However the better approach seems to be to read the page with the proper encoding and leave the quotes alone
var sreader= new StreamReader(fileInfo.Create(), Encoding.GetEncoding(1252));

0
如果您使用String(大写)而不是string,它应该能够处理您提供的任何Unicode。首先尝试这个,看看是否有效。

3
一个名称是另一个的替代词,这并不会改变任何东西。 - BrokenGlass
你说得对!那么我会假设问题中的引号不是2018/9,而可能依赖于语言环境。将其转换为int或short以获取Unicode值,并用之前发布的内容替换\u+该数字。 - kappasims

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接