c# - descomprimir - reparar archivos dbf corruptos
Problemas de codificación con archivos dBase III.dbf en diferentes máquinas (4)
Estoy usando C # y .NET 3.5, tratando de importar algunos datos de viejos archivos dbf utilizando ODBC con Microsoft dBase Driver.
Los dbf están en formato dBase III y usan codificación ibm850 para cadenas.
Ahora, cuando ejecuto mi programa en mi máquina, todos los datos de cadena leídos desde OdbcDataReader salen convertidos a UTF-16 o UTF-8 o algo así, idk y lo guardo como UTF-8 y todo está bien, pero cuando intento utilice este programa en un cuadro de XP, algunos caracteres no se convierten correctamente a UTF-8. ''Õ'' por ejemplo. Puede haber algunos otros también. Los caracteres como ''Ä'', ''Ö'' y ''Ü'' están bien. Este es el problema. Tal vez el ODBC o el controlador usa información de la cultura de la máquina o algo para desordenar todo.
¿Es posible leer cadenas de la base de datos como binario? Tal vez algunas funciones como CONVERT o CAST? ¿O dónde podría encontrar algunas referencias para las funciones SQL y la sintaxis que funciona para este controlador dBase u otros controladores? Busqué y no pude encontrar nada. Me siento tan ciego al usar ODBC y SQL.
En este momento estoy usando un hack temporal que reemplaza todos los σ''s con Õ''s.
¡Gracias!
Código de ejemplo:
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);
Resultado:
E5 en dbf (Õ en 850)
Test.txt en pc1: C3 95 (Õ en UTF-8)
Test.txt en pc2: CF 83 (σ en UTF-8)
¿Ha intentado utilizar el controlador "VFPOleDb" del controlador de Visual Foxpro en su lugar ???
Si sigues teniendo problemas con estos archivos, puedo ayudarte.
¿Qué hay en el "byte de página de códigos", también conocido como "ID de controlador de idioma" (LDID) en el desplazamiento 29 (decimal) en el archivo?
Tengo un lector DBF basado en Python que puede leer casi cualquier tipo de datos de campo y casi cualquier página de códigos: tiene una larga lista compilada desde varias fuentes de mapeo desde el byte de la página de códigos hasta el número de la página de códigos. Las opciones son (1) creer que LDID, entregar Unicode (2) ignorar el LDID, entregar bytes no codificados (3) anular el LDID, decodificar con una página de códigos específica en Unicode. El Unicode por supuesto puede ser codificado en UTF-8.
El lector DBF también realiza una gran cantidad de verificaciones cruzadas razonables que pueden ayudar a investigar por qué VFP piensa que el archivo está dañado.
¿Cómo sabes que está usando IBM850? Otra pieza de código Python que tengo es un prototipo de detector de codificación, que a diferencia de detectores como ''chardet'' que se derivan del código de Mozilla no está centrado en la web y puede reconocer la mayoría de las páginas de códigos antiguas de DOS. Esto puede ayudar.
Una observación: la letra griega minúscula sigma (σ) es 0xE5 en la página de códigos 437, que fue reemplazada por la página de códigos 850 - "pc2" parece un poco desactualizado ...
Si crees que puedo ser de alguna ayuda, siéntete libre de enviarme un correo electrónico a insert_punctuation ("sjmachin", "léxico", "net")
Prueba este código
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)));
Cuando lea un archivo dbf, debe comprender que debe tener en cuenta 3 tipos de codificación:
1. Codificar en qué proveedor de bases de datos lee el archivo. Depende del proveedor y del sistema de operación actual. Esta codificación se usará para recibir conjuntos de bytes. Por ejemplo en mi PC:
cuando uso la cadena de conexión "Fuente de datos = {0}; Proveedor = Microsoft.JET.OLEDB.4.0; Propiedades extendidas = DBase IV; ID de usuario =; Contraseña =;", las cadenas se leen usando la página de códigos 866 (MS-DOS ruso) )
cuando uso la cadena de conexión "Data Source = {0}; Provider = vfpoledb.1; Exclusive = No; Collating Sequence = Machine", las cadenas se leen usando Encoding.Default (página de códigos 1251)
2. Codificación en qué cadenas se escriben en el archivo dbf. Puede recibirse desde 29 bytes de archivo dbf, pero de hecho no importa cómo se marque la codificación del archivo dbf, solo debe saber qué codificación se utilizó. Esta codificación se usará como fuente de codificación durante la conversión de cadenas
3. Codificar a qué cadena se convertirá. Esto es UTF-8 por lo general.
Entonces la conversión de cadena debería verse así:
byte[] bytes = Encoding.GetEncoding(codePage1).GetBytes(reader.GetString(0));
string result = Encoding.UTF8.GetString((Encoding.Convert(Encoding.GetEncoding(codePage2), Encoding.UTF8, bytes)));