Проблемы с кодировкой файлов 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)

вы должны понимать, что вы должны учитывать 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)));
Решение Вопроса

Что находится в «байте кодовой страницы» или «идентификаторе драйвера языка» (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»)

 John Machin25 авг. 2011 г., 10:29
@ Андреас: напишите мне. Что такое LDID файла? С чем ты это читаешь? "испортить символы" не помогает. Показать repr (ожидаемые символы), repr (действительные символы). Если возможно, пришлите мне свой код и файл.
 Andreas25 авг. 2011 г., 15:47
Я отправил вам электронное письмо sjmachin на лексикон.
 Andreas25 авг. 2011 г., 08:45
Привет у меня также есть проблемы с чтением файла Dbase, отлично работает при чтении на моем шведском Windows-клиенте, но портит символы при запуске на английском ОС, вы все еще предлагаете помощь?

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

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

???

 Ivarpoiss04 окт. 2010 г., 18:38
Да, у меня есть. Драйверу Foxpro не понравилась моя база данных - он говорит, что он поврежден, но все выглядело нормально, когда я открыл файл в шестнадцатеричном редакторе и сравнил его со спецификациями формата файла.

Ваш ответ на вопрос