编码翻译在某些电脑上不起作用
本文关键字:电脑 不起作用 翻译 编码 | 更新日期: 2023-09-27 18:24:36
我正在努力解决将Mazovia编码(旧的波兰编码)转换为Unicode的问题。我使用了mazovia编码类的实现,这里有一个链接。我使用这个类来转换DBF文件中的值,方法是:
public static string AsUnicode(string text)
{
string result = System.Text.Encoding.Unicode.GetString(
System.Text.Encoding.Convert(new Mazovia(),
System.Text.Encoding.Unicode,
System.Text.Encoding.GetEncoding(852).GetBytes(text)));
return result;
}
在我使用之前,但不知怎么的,几周后它就停止了工作。公共静态字符串AsLatin2(字符串文本){
string result = System.Text.Encoding.GetEncoding(1250).GetString(
System.Text.Encoding.Convert(new Mazovia(),
System.Text.Encoding.GetEncoding(1250),
new Mazovia().GetBytes(text)));
return result;
}
新的解决方案在我的电脑和我测试过的其他几台电脑上运行良好,但它并不适用于所有设备。在一些网站上,它仍然读着"?"而不是"Ł"之类的标志。
Engoding在波兰语和英语Windows7/8上都能工作,但仅在某些编码上不起作用,我不知道可能有什么问题。有人在编码类方面有类似的问题吗?在不同的Windows操作系统实例上有不同的行为?
这是我正在使用的Mazovia的整个Encodinf实现:
公共密封类MazoviaEncoder:编码器{private Dictionary Translator=new Dictionary();
internal MazoviaEncoder()
{
for (byte i = 0x00; i < 0x80; i++)
{
char c = (char)i;
Translator.Add(c, i); // znaki poniżej 128 to standardowe kody ASCII
}
for (byte i = 0x00; i < 0x80; i++)
{
char c = (char)MazoviaAsUnicode.Content[i];
Translator.Add(c, (byte)(i + 0x80)); // znaki powyżej 127 to kody zgodne z Mazovią - trzeba użyć słownika translacji
}
}
public override int GetByteCount(char[] chars, int index, int count, bool flush)
{
// Mazovia jest jednobajtową stroną kodową, więc ilość bajtów dla podanej długości tekstu "count",
// jest równa tej długości (jeden unikodowy, dwubajtowy znak równa się jednemu bajtowi Mazovii)
return count;
}
public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush)
{
byte b;
for (int i = 0; i < charCount; i++)
{
if (!Translator.TryGetValue(chars[charIndex + i], out b))
b = 0x3F;
bytes[byteIndex + i] = b;
}
return charCount;
}
}
internal static class MazoviaAsUnicode
{
public static readonly short[] Content = {
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x0105, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0107, 0x00C4, 0x0104,
0x0118, 0x0119, 0x0142, 0x00F4, 0x00F6, 0x0106, 0x00FB, 0x00F9,
0x015A, 0x00D6, 0x00DC, 0x00A2, 0x0141, 0x00A5, 0x015B, 0x0192,
0x0179, 0x017B, 0x00F3, 0x00D3, 0x0144, 0x0143, 0x017A, 0x017C,
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0};
}
public sealed class MazoviaDecoder : Decoder
{
private char[] Translator = new char[256];
internal MazoviaDecoder()
{
for (byte i = 0x00; i < 0x80; i++)
{
char c = (char)i;
Translator[i] = c; // znaki poniżej 128 to standardowe kody ASCII
}
for (byte i = 0x00; i < 0x80; i++)
{
char c = (char)MazoviaAsUnicode.Content[i];
Translator[i + 0x80] = c; // znaki powyżej 127 to kody zgodne z Mazovią - trzeba użyć słownika translacji
}
}
public override int GetCharCount(byte[] bytes, int index, int count)
{
// Mazovia jest jednobajtową stroną kodową, więc ilość znaków dla podanej ilości bajtów "count",
// jest równa tej właśnie ilości (jeden bajt Mazovii równa się dwubajtowemu znakowi)
return count;
}
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
for (int i = 0; i < byteCount; i++)
chars[charIndex + i] = Translator[bytes[byteIndex + i]];
return byteCount;
}
}
public class Mazovia : System.Text.Encoding
{
public static MazoviaEncoder GetMazoviaEncoder()
{
return new MazoviaEncoder();
}
public static MazoviaDecoder GetMazoviaDecoder()
{
return new MazoviaDecoder();
}
public override int GetByteCount(char[] chars, int index, int count)
{
return GetMazoviaEncoder().GetByteCount(chars, index, count, false);
}
public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
return GetMazoviaEncoder().GetBytes(chars, charIndex, charCount, bytes, byteIndex, false);
}
public override int GetCharCount(byte[] bytes, int index, int count)
{
return GetMazoviaDecoder().GetCharCount(bytes, index, count);
}
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
return GetMazoviaDecoder().GetChars(bytes, byteIndex, byteCount, chars, charIndex);
}
public override int GetMaxByteCount(int charCount)
{
return charCount;
}
public override int GetMaxCharCount(int byteCount)
{
return byteCount;
}
}
public class External
{
[Microsoft.SqlServer.Server.SqlFunction()]
public static SqlString AsMazovia(SqlString text)
{
if (text.IsNull)
return SqlString.Null;
byte[] b = text.GetNonUnicodeBytes();
char[] c = new char[b.Length];
Mazovia Mazovia = new Mazovia();
Mazovia.GetChars(b, 0, b.Length, c, 0);
StringBuilder sb = new StringBuilder(b.Length);
foreach (var i in c)
sb.Append(i);
SqlString result = new SqlString(sb.ToString());
return result.Value;
}
public static string AsUnicode(string text)
{
string result = System.Text.Encoding.Unicode.GetString(
System.Text.Encoding.Convert(new Mazovia(),
System.Text.Encoding.Unicode,
System.Text.Encoding.GetEncoding(852).GetBytes(text)));
return result;
}
}
我用来从.DBF文件加载数据的代码如下:
string strAccessConn = @"Provider=vfpoledb;uid=admin;Collating Sequence=machine;Data Source=...'latin2;CodePage=852";
string strAccessSelect = "SELECT NAME FROM TABLE";
DataSet myDataSet = new DataSet();
OleDbConnection myAccessConn = null;
myAccessConn = new OleDbConnection(strAccessConn);
OleDbCommand myAccessCommand = new OleDbCommand(strAccessSelect, myAccessConn);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(myAccessCommand);
myAccessConn.Open();
myDataAdapter.Fill(myDataSet, "TABLE");
return null;
myAccessConn.Close();
DataTableCollection dta = myDataSet.Tables;
foreach (DataTable dt in dta)
{
...
}
这是bith-odbc和oleDB使用的许多提供者之一。
如何在Windows操作系统版本无关的情况下使用C#读取用Mazovia编码的DBF文件
我不确定你的案子到底出了什么问题。
尽管有些文章说应该可以使用Microsoft OLE DB Provider for Visual FoxPro读取它(例如,堆栈溢出:我如何读取dbase文件并应用不同的解码?),但幸运的是,DBF文件格式有文档记录(例如,Stack Overflow:将FoxPro导出到dbase的代码或工具),并且可以在没有任何难以配置的第三方工具的情况下读取。
Delphi
语言文件格式的一个可靠的可执行规范可在SourceForge.net上现已废弃的Delphi和BCB的tDBF组件存储库中找到
另一个现已废弃的C#
语言文件格式的可执行规范(可靠性未知)可在https://github.com/ekonbenefits/dotnetdbf.
特别是https://github.com/ekonbenefits/dotnetdbf/blob/master/DotNetDBF/DBFReader.cs#L258是您的自定义解码器可能插入的位置,或者您可能将Mazovia
类插入的位置https://github.com/ekonbenefits/dotnetdbf/blob/master/DotNetDBF/DBFBase.cs#L27
在你的完全控制下使用你的自定义C#阅读器应该会给你操作系统版本的独立性和可靠性,除此之外,你的用户不会被迫进入一些驱动程序版本/32bit/64bit地狱。