我正在阅读各种格式和语言的文件,我目前正在使用一个小编码库来尝试检测正确的编码(http://www.codeproject.com/KB/recipes/DetectEncoding.aspx)。
这很不错,但偶尔还会错过。 (多语言文件)
我的大多数潜在用户对编码的理解很少(我希望最好的是“它与字符有关”)并且不太可能在列表中选择正确的编码,所以我我想让他们循环通过不同的编码,直到找到正确的编码只需点击一个按钮。
显示问题?点击这里尝试不同的编码! (无论如何这是概念)
实现类似内容的最佳方式是什么?
编辑:看起来我没有表达得足够清楚。通过“循环编码”,我不是指“如何循环编码?”
我的意思是“如何让用户按顺序尝试不同的编码而不重新加载文件?”
这个想法更像是这样的:假设文件加载了错误的编码。显示一些奇怪的字符。用户将单击“下一编码”或“先前编码”按钮,并且将以不同的编码转换该字符串。用户只需要一直点击,直到找到正确的编码。 (无论哪种编码看起来对用户有用都会很好)。只要用户点击“下一步”,他就有合理的机会解决他的问题。
到目前为止,我发现使用当前编码将字符串转换为字节,然后将字节转换为下一个编码,将这些字节转换为字符,然后将字符串转换为字符串......可行,但我想知道如果没有更简单的方法来做到这一点。
例如,如果有一个方法可以读取字符串并使用不同的编码返回它,例如“render(string,encoding)”。
非常感谢您的答案!
答案 0 :(得分:14)
以字节形式读取文件,然后使用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)的结果进行进一步处理。
答案 1 :(得分:4)
(删除问题更新后的原始答案)
例如,如果有方法 这将读取一个字符串并返回它 使用不同的编码,一些东西 比如“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();
}
}
};
}
}
答案 2 :(得分:0)
你可以让用户输入应该在文件中出现的一些单词(带有“特殊”字符)吗?
您可以自己搜索所有编码,看看这些单词是否存在。
答案 3 :(得分:0)
小心臭名昭着的'Notepad bug'。无论你尝试什么,它都会咬你,但是......你可以在MSDN(以及其他地方)找到一些关于编码及其挑战的good discussions。
答案 4 :(得分:0)
您必须将原始数据保存为字节数组或MemoryStream,然后可以转换为新编码,一旦您已将数据转换为字符串,就无法可靠地返回到原始表示。
答案 5 :(得分:0)
这样的事情怎么样:
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);
}
第一次尝试使用加载文件;然后使用Try Encoding。