C# &引用É&引用;无法正确转换为两个字节

C# &引用É&引用;无法正确转换为两个字节,c#,unicode,fonts,C#,Unicode,Fonts,除此之外,我还有一个补充问题 我发现一首歌的标题是“É” 我的代码: var playList = new StreamWriter(playlist, false, Encoding.UTF8); - 将其转换为以下字节: 195 137 输出为Ã后跟一个正方形(这是一个无法以当前字体打印的字符) 我已经将同一个文件导出到Media Monkey中的播放列表中,它将“Ô写为“É”——我假设这是正确的(正如KennyTM指出的) 我的问题是,如何获得“‰”符号输出?我需要选择不同的字体吗

除此之外,我还有一个补充问题

我发现一首歌的标题是“É”

我的代码:

var playList = new StreamWriter(playlist, false, Encoding.UTF8);
-

将其转换为以下字节:

195
137
输出为Ã后跟一个正方形(这是一个无法以当前字体打印的字符)

我已经将同一个文件导出到Media Monkey中的播放列表中,它将“Ô写为“É”——我假设这是正确的(正如KennyTM指出的)

我的问题是,如何获得“‰”符号输出?我需要选择不同的字体吗?如果需要,选择哪种字体

更新

人们似乎没有抓住重点

我可以使用

playList.WriteLine("É");
这不是问题所在

问题是Media Monkey要求文件采用以下格式:

#EXTINFUTF8:140,Yann Tiersen - Comptine D'Un Autre Été: L'Après Midi
#EXTINF:140,Yann Tiersen - Comptine D'Un Autre Été: L'Après Midi
#UTF8:04-Comptine D'Un Autre Été- L'Après Midi.mp3
04-Comptine D'Un Autre Été- L'Après Midi.mp3
其中所有的“高ascii”(因为缺少更好的术语)都被写成一对字符

更新2

我应该将
c9
替换为
c389

我本来打算把我实际得到的东西放进去,但是在做这个测试的过程中,我设法得到了一个测试程序,以正确的格式“原样”输出文本。因此,我需要做更多的调查。

我不做C#但症状告诉我,您确实是以UTF-8的形式编写的,但是您查看写入输出的输出/控制台/应用程序/任何东西都不是使用UTF-8,而是使用ISO-8859-1来显示它们,MediaMonkey使用CP1252来显示它们

如果在IDE控制台中查看它们,则需要将IDE配置为使用
UTF-8
作为控制台和文本文件编码

更新您显然希望将
UTF-8
数据写入
CP-1252
。现在问题更清楚了。同样,我不做C#,但Java等价物是:

Writer writer = new OutputStreamWriter(new FileOutputStream("file.ext"), "CP-1252");
writer.write(someUTF8String); // Will be written as CP-1252. "É" would become "É"
希望这能提供一些见解。

我不做C#但症状告诉我,您确实是以UTF-8的形式编写的,但是您查看编写的输出的输出/控制台/应用程序/任何东西都不是使用UTF-8,而是使用ISO-8859-1来显示它们,MediaMonkey使用CP1252来显示它们

如果在IDE控制台中查看它们,则需要将IDE配置为使用
UTF-8
作为控制台和文本文件编码

更新您显然希望将
UTF-8
数据写入
CP-1252
。现在问题更清楚了。同样,我不做C#,但Java等价物是:

Writer writer = new OutputStreamWriter(new FileOutputStream("file.ext"), "CP-1252");
writer.write(someUTF8String); // Will be written as CP-1252. "É" would become "É"

希望这能提供一些见解。

像这样使用
Convert.ToChar
几乎肯定是个坏主意。你基本上是在两次编码

您应该自己执行转换,然后直接写入流,或者让
StreamWriter
执行转换。如果您试图自己执行转换,为什么要使用
StreamWriter

您正在尝试写入二进制文件还是简单的文本文件?如果它是一个简单的文本文件,只需使用
StreamWriter
就可以进行转换。如果是二进制文件,请使用
而不是
流编写器
,并在需要时直接执行文本编码,然后将字节直接写入流

编辑:以下是您的原始代码发生的情况:

Encoding.UTF8.GetBytes(text) => byte[] { 0xc3, 0x89 };

Convert.ToChar(0xc3) => char U+00C3
StreamWriter writes U+00C3 as byte[] { 0xc3, 0x83 };

Convert.ToChar(0x89) => char U+0089
StreamWriter writes U+00C3 as byte[] { 0xc2, 0x89 };

这就是为什么要将c3 83 c2 89写入文件。

像这样使用
Convert.ToChar
几乎肯定是个坏主意。你基本上是在两次编码

您应该自己执行转换,然后直接写入流,或者让
StreamWriter
执行转换。如果您试图自己执行转换,为什么要使用
StreamWriter

您正在尝试写入二进制文件还是简单的文本文件?如果它是一个简单的文本文件,只需使用
StreamWriter
就可以进行转换。如果是二进制文件,请使用
而不是
流编写器
,并在需要时直接执行文本编码,然后将字节直接写入流

编辑:以下是您的原始代码发生的情况:

Encoding.UTF8.GetBytes(text) => byte[] { 0xc3, 0x89 };

Convert.ToChar(0xc3) => char U+00C3
StreamWriter writes U+00C3 as byte[] { 0xc3, 0x83 };

Convert.ToChar(0x89) => char U+0089
StreamWriter writes U+00C3 as byte[] { 0xc2, 0x89 };

这就是为什么要将c3 83 c2 89写入文件。

StreamWriter
已经将发送的字符转换为UTF-8 — 这就是它的全部目的。扔掉
WriteUTF8
;它坏了,没用了

WriteUTF8
是获取字符,将它们转换为UTF-8字节,将每个单个字节转换为它在当前代码页中映射到的字符,然后用UTF-8编码每个字符。因此,在最好的情况下,您有一个双UTF-8编码字符串;在最坏的情况下,您完全丢失了系统中未映射的字节e页面指令集;对于DBCS代码页尤其糟糕。)

Media Monkey的问题可能只是它根本不支持UTF-8或Unicode文件名。请尝试让它播放(并导出播放列表)不适合系统代码页字符的文件,例如将文件重命名为
αβγ.mp3

编辑:

好的,您在同一个文件中得到的是混合编码:难怪文本编辑器在打开它时会遇到问题。未注释和
#definef
行位于系统默认代码页中,用于支持无法读取Unicode文件名的媒体播放器。系统中没有任何文件名字符对于不知道
#UTF8
(以及
#extefutf8
(用于说明)行的任何内容,代码页(如上面的希腊文,在Western Windows安装中)将被损坏且不可打印

因此,如果这是您的目标格式,则需要获取两个编码和u
private static void writePlaylistEntry(Stream playlist, string filename, int length) {
    Encoding utf8= new UTF8Encoding(false);
    Encoding ansi= Encoding.Default;
    playlist.Write(utf8.GetBytes("#EXTINFUTF8:"+length+","+filename+"\n"));
    playlist.Write(ansi.GetBytes("#EXTINF:"+length+","+filename+"\n"));
    playlist.Write(utf8.GetBytes("#UTF8:"+filename+"\n"));
    playlist.Write(ansi.GetBytes(filename+"\n"));
}
 private static void WriteUTF8(...)
static void Main(string[] args)
{
    string fileName = @"C:\Temp\Test.m3u";
    using (StreamWriter writer = new StreamWriter(fileName, false,
        Encoding.GetEncoding(1252)))
    {
        writer.WriteLine("#EXTM3U");
        writer.WriteLine("#EXTINF:140,Yann Tiersen " +
            "- Comptine D'Un Autre Été: L'Après Midi");
        writer.WriteLine("04-Comptine D'Un Autre Été- L'Après Midi.mp3");
    }
}
var playList = new StreamWriter(playlist, false, Encoding.Default);
playList.WriteLine("#EXTM3U");

foreach (string track in tracks)
{
    // Read ID3 tags from file
    var info = new FileProperties(track);

    // Write extended info (#EXTINF:<time>,<artist> - <title>
    if (Encoding.UTF8.GetBytes(info.Artist).Length != info.Artist.Length ||
        Encoding.UTF8.GetBytes(info.Title).Length != info.Title.Length)
    {
        playList.Close();
        playList = new StreamWriter(playlist, true, Encoding.UTF8);

        playList.WriteLine(string.Format("#EXTINFUTF8:{0},{1} - {2}",
                           info.Duration, info.Artist, info.Title));

        playList.Close();
        playList = new StreamWriter(playlist, true, Encoding.Default);
    }

    playList.WriteLine(string.Format("#EXTINF:{0},{1} - {2}",
                       info.Duration, info.Artist, info.Title));

    // Write the name of the file (removing the drive letter)
    string file = Path.GetFileName(track);
    if (Encoding.UTF8.GetBytes(file).Length != file.Length)
    {
        playList.Close();
        playList = new StreamWriter(playlist, true, Encoding.UTF8);

        playList.WriteLine(string.Format("#UTF8:{0}", file));

        playList.Close();
        playList = new StreamWriter(playlist, true, Encoding.Default);
    }

    playList.WriteLine(file);
}

playList.Close();