[英]C#: Cycle through encodings
我正在阅读各种格式和语言的文件,我目前正在使用一个小型编码库来尝试检测正确的编码( 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));
所以你只需要加载一次文件。 您可以根据文件的原始字节使用每种编码。 用户可以 select 正确的一个,您可以使用 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();
}
}
};
}
}
你能让用户输入一些应该出现在文件中的单词(带有“特殊”字符)吗?
您可以自己搜索所有编码以查看这些单词是否存在。
您必须将原始数据保留为字节数组或 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。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.