2010-10-02 3 views
0

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

dbf находятся в формате dBase III и используют кодировку ibm850 для строк.

Теперь, когда я запускаю свою программу на своей машине, все строковые данные, считываемые из OdbcDataReader, выводятся в UTF-16 или UTF-8 или что-то в этом роде, и я сохраняю его как 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 в DBF (О в 850)

Test.txt на ПК1: С3 95 (Х в UTF-8)

Test.txt на pc2: CF 83 (σ в UTF-8)

ответ

2

Если у вас по-прежнему возникают проблемы с этими файлами, я могу вам помочь.

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

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

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

Откуда вы знаете, что он использует IBM850? Еще один фрагмент кода Python, который у меня есть, - это прототип детектора кодирования, который в отличие от таких детекторов, как «chardet», которые получены из кода Mozilla, не является веб-ориентированным и может с радостью распознавать большинство старых кодовых страниц DOS - это может помочь.

Наблюдение: сигма с буквой в нижнем регистре греческой буквы (σ) составляет 0xE5 в кодировке 437, которая была удалена кодовой страницей 850 - «pc2» кажется немного устаревшей ...

Если вы думаете, что может быть какой-либо помощи, не стесняйтесь, пишите мне на insert_punctuation («sjmachin», «лексикон», «чистый»)

+0

Привет, у меня также есть проблемы с чтением файла Dbase, отлично работает при чтении на моем шведском клиенте Windows, но запутывает символы при запуске на английском языке os, вы все еще предлагаете помощь? – Andreas

+0

@ Андреас: напишите мне. Что такое LDID файла? С чем вы его читаете? «messes up characters» не помогает. Показать превью (ожидаемые символы), repr (фактические символы). Если возможно, пришлите мне свой код и свой файл. –

+0

Я отправил вам письмо sjmachin в lexicon dot net – Andreas

0

Вы пытались использовать драйвер Visual FoxPro «V FPOleDb "вместо ???

+0

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

1

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

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

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

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

  • , когда я использую строку подключения «Data Source = {0}; Provider = Microsoft.Jet.OLEDB.4.0; Extended Properties = Dbase IV; User ID = ; Password = ; "строки считываются с помощью кодовой страницы 866 (русский MS-DOS)

  • , когда я использую строку подключения" Data Source = {0}; Provider = vfpoledb.1; Exclusive = Нет, Collating Sequence = машина ", строки считываются с использованием Encoding.Default (1251 кодовая страница)

2.Encoding, в котором строки записываются в файл dbf. Его можно получить из 29 байт файла dbf, но на самом деле неважно, как помечено кодирование файла dbf, вы должны просто знать, какая кодировка была использована. Это кодирование должно использоваться как исходное кодирование при преобразовании строки

3.Encoding, в которую должна быть преобразована строка. Обычно это UTF-8.

Так преобразование строки должно выглядеть следующим образом:

byte[] bytes = Encoding.GetEncoding(codePage1).GetBytes(reader.GetString(0)); 

string result = Encoding.UTF8.GetString((Encoding.Convert(Encoding.GetEncoding(codePage2), Encoding.UTF8, bytes))); 
Смежные вопросы