Проблемы с кодировкой файлов dBase III .dbf на разных компьютерах - PullRequest
0 голосов
/ 02 октября 2010

Я использую C # и .NET 3.5, пытаюсь импортировать некоторые данные из старых файлов dbf, используя ODBC с драйвером Microsoft dBase.

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);

Результат:

E5 в дБф (Õ в 850)

Test.txt на ПК1: C3 95 (Õ в UTF-8)

Test.txt на ПК2: CF 83 (σ в UTF-8)

Ответы [ 4 ]

2 голосов
/ 12 ноября 2010

Если у вас все еще есть проблема с этими файлами, я могу вам помочь.

Что находится в "байте кодовой страницы" или "идентификаторе драйвера языка" (LDID) со смещением 29 (десятичное число) в файле?

У меня есть читатель DBF на основе Python, который может читатьпрактически любой тип данных поля и практически любая кодовая страница - он имеет длинный список, составленный из различных источников отображений от байта кодовой страницы до номера кодовой страницы.Возможные варианты: (1) полагать, что LDID, доставлять Unicode (2) игнорировать LDID, доставлять незакодированные байты (3) переопределять LDID, декодировать с определенной кодовой страницей в Unicode.Разумеется, Unicode может быть затем закодирован в UTF-8.

Считыватель DBF также выполняет множество проверок на разумность, которые могут помочь выяснить, почему VFP считает файл поврежденным.

Откуда ты знаешь, что он использует IBM850?Другой фрагмент кода Python, который у меня есть, представляет собой детектор кодирования прототипа, который в отличие от таких детекторов, как 'chardet', которые получены из кода Mozilla, не ориентирован на web и может с радостью распознавать большинство старых кодовых страниц DOS - это может помочь.1010 * Замечание: сигма строчной буквы греческого алфавита (σ) равна 0xE5 в кодовой странице 437, за которой следовала кодовая страница 850 - «pc2» кажется немного устаревшей ...

Если вы думаете, что я могулюбая помощь, не стесняйтесь, напишите мне на insert_punctuation ("sjmachin", "lexicon", "net")

2 голосов
/ 03 мая 2011

Попробуйте этот код.

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)));
1 голос
/ 02 ноября 2016

Когда вы читаете файл dbf, вы должны понимать, что вы должны учитывать 3 типа кодировки:

1. Кодирование, в котором поставщик базы данных читает файл.Это зависит от провайдера и текущей операционной системы.Это кодирование должно использоваться для получения байтового массива.Например, на моем ПК:

  • , когда я использую строку подключения "Источник данных = {0}; Поставщик = Microsoft.JET.OLEDB.4.0; Расширенные свойства = DBase IV; Идентификатор пользователя =; Password =; ", строки читаются с использованием кодовой страницы 866 (русская MS-DOS)

  • , когда я использую строку подключения" Источник данных = {0}; Provider = vfpoledb.1;Exclusive = No; Collating Sequence = Machine ", строки читаются с использованием 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)));
0 голосов
/ 04 октября 2010

Вы пытались использовать вместо драйвера Visual Foxpro драйвер "VFPOleDb" ???

...