Проблемы с кодировкой файлов dBase III .dbf на разных компьютерах
Я использую C# и.NET 3.5, пытаюсь импортировать некоторые данные из старых файлов dbf, используя ODBC с Microsoft dBase Driver.
DBF в формате dBase III и используют кодирование ibm850 для строк.
Теперь, когда я запускаю свою программу на моей машине, все строковые данные, считанные из OdbcDataReader, преобразуются в UTF-16 или UTF-8 или что-то в этом роде, мы с idk сохраняем его как UTF-8, и все в порядке, но когда я пытаюсь используйте эту программу в окне XP, некоторые символы не будут правильно преобразованы в UTF-8. 'Õ' например. Там могут быть и другие. Такие символы, как "Ä", "Ö" и "Ü" в порядке. Это проблема. Может быть, ODBC или драйвер использует некоторую информацию о культуре машины или что-то еще, чтобы все испортить.
Можно ли читать строки из базы данных как двоичные? Может быть, некоторые функции, такие как CONVERT или CAST? Или где я могу найти ссылки на функции и синтаксис SQL, которые работают для этого драйвера dBase или других драйверов? Я искал вокруг и не мог ничего найти. Я чувствую себя настолько слепым при использовании ODBC и SQL.
Прямо сейчас я использую временный хак, который заменяет все σ на Õ.
Спасибо!
Пример кода:
System.Data.Odbc.OdbcConnection oConn = new System.Data.Odbc.OdbcConnection();
oConn.ConnectionString = @"Driver={Microsoft dBase Driver (*.dbf)};DriverID=277;Dbq=" + dbPath + ";";
oConn.Open();
System.Data.Odbc.OdbcCommand oCmd = oConn.CreateCommand();
oCmd.CommandText = @"SELECT name FROM " + dbPath + "TABLE.DBF";
System.Data.Odbc.OdbcDataReader reader = oCmd.ExecuteReader();
reader.Read();
byte[] buf = Encoding.UTF8.GetBytes(reader.GetString(0));
BinaryWriter writer = new BinaryWriter(File.Open(@"C:\DBF\Test.txt", FileMode.Create));
writer.Write(buf);
Результат:
Е5 в дБф (Õ в 850)
Test.txt на ПК1: C3 95 (Õ в UTF-8)
Test.txt на ПК2: CF 83 (σ в UTF-8)
4 ответа
Если у вас все еще есть проблема с этими файлами, я могу вам помочь.
Что находится в "байте кодовой страницы" или "идентификаторе драйвера языка" (LDID) со смещением 29 (десятичное число) в файле?
У меня есть читатель DBF на основе Python, который может читать практически любой тип данных поля и практически любую кодовую страницу - он имеет длинный список, составленный из различных источников отображений от байта кодовой страницы до номера кодовой страницы. Возможные варианты: (1) полагать, что LDID, доставлять Unicode (2) игнорировать LDID, доставлять незакодированные байты (3) переопределять LDID, декодировать с определенной кодовой страницей в Unicode. Юникод, конечно, может быть затем закодирован в UTF-8.
Считыватель DBF также выполняет множество проверок на разумность, что может помочь выяснить, почему VFP считает, что файл поврежден.
Откуда ты знаешь, что он использует IBM850? Другой фрагмент кода Python, который у меня есть, представляет собой детектор кодирования прототипа, который в отличие от таких детекторов, как 'chardet', которые получены из кода Mozilla, не ориентирован на web и может успешно распознавать большинство старых кодовых страниц DOS - это может помочь.
Замечание: сигма строчной буквы греческого алфавита (σ) равна 0xE5 в кодовой странице 437, за которой последовала кодовая страница 850 - "pc2" кажется немного устаревшим...
Если вы думаете, что я могу вам чем-то помочь, не стесняйтесь писать мне на электронный адрес insert_punctuation ("sjmachin", "lexicon", "net")
Попробуйте этот код.
var oConn = new System.Data.Odbc.OdbcConnection();
oConn.ConnectionString = "Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" + dbPath;
oConn.Open();
var oCmd = oConn.CreateCommand();
oCmd.CommandText = @"SELECT name FROM " + dbPath + "TABLE.DBF";
var reader = oCmd.ExecuteReader();
reader.Read();
byte[] A = Encoding.GetEncoding(Encoding.Default.CodePage).GetBytes(reader.GetString(0));
string p = Encoding.Unicode.GetString((Encoding.Convert(Encoding.GetEncoding(850), Encoding.Unicode, A)));
Когда вы читаете файл dbf, вы должны понимать, что вы должны учитывать 3 типа кодировки:
1. Кодирование, в котором поставщик базы данных читает файл. Это зависит от провайдера и текущей операционной системы. Это кодирование должно использоваться для получения байтового массива. Например на моем ПК:
когда я использую строку подключения "Источник данных ={0}; поставщик =Microsoft.JET.OLEDB.4.0; расширенные свойства =DBase IV; идентификатор пользователя =; пароль =;", строки считываются с использованием кодовой страницы 866 (русская версия MS-DOS)
когда я использую строку подключения "Источник данных ={0}; поставщик =vfpoledb.1; исключительный = нет; последовательность сортировки = машина", строки считываются с использованием Encoding.Default (кодовая страница 1251)
2. Кодирование, в котором строки записываются в файл dbf. Он может быть получен из 29 байт файла dbf, но на самом деле не имеет значения, как помечается кодировка файла dbf, вы просто должны знать, какая кодировка использовалась. Это кодирование должно использоваться в качестве исходного кодирования во время преобразования строки
3. Кодирование в какую строку необходимо преобразовать. Обычно это UTF-8.
Таким образом, преобразование строки должно выглядеть так:
byte[] bytes = Encoding.GetEncoding(codePage1).GetBytes(reader.GetString(0));
string result = Encoding.UTF8.GetString((Encoding.Convert(Encoding.GetEncoding(codePage2), Encoding.UTF8, bytes)));
Вы пытались использовать вместо этого драйвер Visual Foxpro "VFPOleDb"???