C#:循环编码

我正在阅读各种格式和语言的文件,我目前正在使用一个小编码库来尝试检测正确的编码( http://www.codeproject.com/KB/recipes/DetectEncoding.aspx )。

这很不错,但偶尔也会错过。 (多语言文件)

我的大多数潜在用户对编码的理解很少(我希望最好的是“它与字符有关”)并且不太可能在列表中选择正确的编码,所以我想让他们循环通过不同的编码,直到通过点击按钮找到正确的编码。

显示问题? 点击这里尝试不同的编码! (那就是这个概念)

实现类似的东西最好的方法是什么?


编辑:看起来我没有表达得足够清楚。 通过“循环编码”,我不是指“如何循环编码?”

我的意思是“如何让用户按顺序尝试不同的编码而不重新加载文件?”

这个想法更像是这样的:假设文件加载了错误的编码。 显示一些奇怪的字符。 用户将单击“下一编码”或“先前编码”按钮,并且将以不同的编码转换该字符串。 用户只需要一直点击,直到找到正确的编码。 (无论编码看起来对用户有什么好处都可以。) 只要用户可以点击“下一步”,他就有合理的机会解决他的问题。

到目前为止我发现的包括使用当前编码将字符串转换为字节,然后将字节转换为下一个编码,将这些字节转换为字符,然后将字符串转换为字符串…可行,但我想知道是否存在这是一种更简单的方法。

例如,如果有一个方法可以读取字符串并使用不同的编码返回它,例如“render(string,encoding)”。


非常感谢你的答案!

将文件作为字节读取,然后使用Encoding.GetString方法。

byte[] data = System.IO.File.ReadAllBytes(path); Console.WriteLine(Encoding.UTF8.GetString(data)); Console.WriteLine(Encoding.UTF7.GetString(data)); Console.WriteLine(Encoding.ASCII.GetString(data)); 

所以你只需加载一次文件。 您可以根据文件的原始字节使用每个编码。 用户可以选择正确的一个,你可以使用Encoding.GetEncoding(…)。GetString(data)的结果进行进一步处理。

(删除问题更新后的原始答案)

例如,如果有一个方法可以读取字符串并使用不同的编码返回它,例如“render(string,encoding)”。

我认为你不能重复使用字符串数据。 事实是:如果编码错误,则此字符串可被视为已损坏。 它可能很容易在可能看起来的角色中包含乱码。 特别是,许多编码可能会原谅BOM /序言的存在/不存在,但是你会用它重新编码吗? 没有它?

如果您愿意冒险(我不会),您可以使用最后一个编码重新编码本地字符串:

 // I DON'T RECOMMEND THIS!!!! byte[] preamble = lastEncoding.GetPreamble(), content = lastEncoding.GetBytes(text); byte[] raw = new byte[preamble.Length + content.Length]; Buffer.BlockCopy(preamble, 0, raw, 0, preamble.Length); Buffer.BlockCopy(content, 0, raw, preamble.Length, content.Length); text = nextEncoding.GetString(raw); 

实际上,我相信你能做的最好的事情就是保持原始的byte[] – 继续提供不同的渲染(通过不同的编码),直到他们喜欢一个。 就像是:

 using System; using System.IO; using System.Text; using System.Windows.Forms; class MyForm : Form { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.Run(new MyForm()); } ComboBox encodings; TextBox view; Button load, next; byte[] data = null; void ShowData() { if (data != null && encodings.SelectedIndex >= 0) { try { Encoding enc = Encoding.GetEncoding( (string)encodings.SelectedValue); view.Text = enc.GetString(data); } catch (Exception ex) { view.Text = ex.ToString(); } } } public MyForm() { load = new Button(); load.Text = "Open..."; load.Dock = DockStyle.Bottom; Controls.Add(load); next = new Button(); next.Text = "Next..."; next.Dock = DockStyle.Bottom; Controls.Add(next); view = new TextBox(); view.ReadOnly = true; view.Dock = DockStyle.Fill; view.Multiline = true; Controls.Add(view); encodings = new ComboBox(); encodings.Dock = DockStyle.Bottom; encodings.DropDownStyle = ComboBoxStyle.DropDown; encodings.DataSource = Encoding.GetEncodings(); encodings.DisplayMember = "DisplayName"; encodings.ValueMember = "Name"; Controls.Add(encodings); next.Click += delegate { encodings.SelectedIndex++; }; encodings.SelectedValueChanged += delegate { ShowData(); }; load.Click += delegate { using (OpenFileDialog dlg = new OpenFileDialog()) { if (dlg.ShowDialog(this)==DialogResult.OK) { data = File.ReadAllBytes(dlg.FileName); Text = dlg.FileName; ShowData(); } } }; } } 

你能让用户输入一些应该在文件中出现的单词(带有“特殊”字符)吗?

您可以自己搜索所有编码,看看这些单词是否存在。

谨防臭名昭着的’ Notepad bug ‘。 无论你尝试什么,它都会咬你…但你可以在MSDN(和其他地方)找到关于编码及其挑战的一些很好的讨论 。

您必须将原始数据保存为字节数组或MemoryStream,然后您可以转换为新编码,一旦您已将数据转换为字符串,就无法可靠地返回到原始表示。

这样的事情怎么样:

 public string LoadFile(string path) { stream = GetMemoryStream(path); string output = TryEncoding(Encoding.UTF8); } public string TryEncoding(Encoding e) { stream.Seek(0, SeekOrigin.Begin) StreamReader reader = new StreamReader(stream, e); return reader.ReadToEnd(); } private MemoryStream stream = null; private MemorySteam GetMemoryStream(string path) { byte[] buffer = System.IO.File.ReadAllBytes(path); return new MemoryStream(buffer); } 

第一次尝试使用LoadFile; 然后使用TryEncoding。