PDA

Ver la Versión Completa : Desempaquetar campos numéricos comprimidos de archivo


newtron
23-05-2012, 17:24:03
Hola a tod@s.

Necesito leer un fichero creado con btrieve para pasarlo a mi aplicación. Con la instrucción BUTIL saco los registros a un fichero de texto pero me encuentro con que los campos numéricos están empaquetados. Para los que conozcan el BASIC quiero recordar que se empaquetaban/desempaquetaban con la instrucción cvi/cvs mki/mks.

¿Hay alguna manera desde Delphi de poder leer y desempaquetar estos campos o me tendré que preparar un programita en BASIC (horror porque no me acuerdo de nada)?

Dejo aquí un archivo de muestra por si a alguien le hace chiste y le echa un vistazo.

Gracias y un saludo

Casimiro Notevi
23-05-2012, 20:26:18
En torrys (http://www.torry.net/quicksearchd.php?String=btrieve&Title=Yes) hay algunos componentes para acceder desde delphi a bases de datos btrieve/pervasive, a ver si te sirve.
También he encontrado esto (http://www.dbcoretech.com/?page_id=381), es libre.

newtron
24-05-2012, 18:55:04
Gracias, le echaré un vistazo y te cuento.

newtron
24-05-2012, 19:32:22
Parece que estos programas lo que hacen es algo similar al BUTIL que viene con las BTRIEVE que es generar un fichero de texto a partir del fichero original pero no me resuelve el problema de los números empaquetados.

Seguiremos buscando la forma.

Casimiro Notevi
24-05-2012, 19:51:25
"Números empaquetados", ¿te refieres a big endian y little endian?

unsigned long blockLength = *blockLengthPtr++ << 24;
blockLength |= *blockLengthPtr++ << 16;
blockLength |= *blockLengthPtr++ << 8;
blockLength |= *blockLengthPtr;

unsigned long dataLength = *dataLengthPtr++ << 24;
dataLength |= *dataLengthPtr++ << 16;
dataLength |= *dataLengthPtr++ << 8;
dataLength |= *dataLengthPtr;

Casimiro Notevi
24-05-2012, 19:53:10
Mira esta página (http://stackoverflow.com/questions/5320439/how-do-i-swap-endian-ness-byte-order-of-a-variable-in-javascript), creo que ahí tienes la solución


Y aquí un ejemplo sencillo, que en teoría funciona;

function SwapEndian(Value: integer): integer; register; overload;
asm
bswap eax
end;

function SwapEndian(Value: smallint): smallint; register; overload;
asm
xchg al, ah
end;

egostar
24-05-2012, 20:06:45
Hola newtron

Hasta donde recuerdo (usé btrieve y butil en los 90's) y el butil te generaba un archivo csv de la info, voy a escarbar en mis respaldos a ver si conservo aún la linea de comandos que usaba para eso, aunque era para DOS, no se si cambiaron algo en esos programas.

Saludos

Casimiro Notevi
24-05-2012, 21:28:08
Veamos, creo que esto:

var
before, after : Word;
begin
// Set up out starting number
before := $3C; // Hex 3C = 003C in the Word

// Shift left by 12 will lose the top 12 bits of the Word
after := before Shl 12;

ShowMessageFmt('Before : %x',);
ShowMessageFmt('After shift left : %x',[after]);

[B]// Shifting right by 12 will not recover the lost data
after := after Shr 12;

ShowMessageFmt('After shift right : %x',[after]);
end;


Mira los ejemplos de shr (http://www.delphibasics.co.uk/RTL.asp?Name=Shr) y shl (http://www.delphibasics.co.uk/RTL.asp?Name=Shl) en http://www.delphibasics.co.uk

newtron
25-05-2012, 09:27:16
Gracias egostar, el archivo ya lo tengo extraido con BUTIL. El problema que tengo es que dentro del registro hay campos numéricos empaquetados que no sé cómo extraerlos desde delphi. Esto en basic se hacían con unas instrucciones que no sé si tienen equivalencia en delphi.

En la imagen se ve un ejemplo del archivo en el que los muñecos de ciertos campos son los campos numéricos que os comento.

Casimiro, no sé si esto que me indicas sirve para lo que estoy buscando, lo estudiaré un poco porque por encima no me entero de qué va.

Gracias y un saludo.

http://img51.imageshack.us/img51/1969/pantallarx.jpg

egostar
25-05-2012, 15:52:31
Entiendo,

La otra opción es utilizar el manejador de bases de datos Btrieve, se llama Xtrieve, aunque lo que yo usé era para DOS, desconozco si tienes esa herramienta y desconozco si aún existe o se pueda descarga libremente.

Por cierto, hasta donde recuerdo, los tipos decimales son BCD, y me parece que BUTIL exporta los valores numéricos (decimal, entero) como binarios.

Saludos

Casimiro Notevi
25-05-2012, 16:54:52
Será mucho pedir preguntar si tienes el código fuente de esas funciones cvi/cvs mki/mks :)
Para saber qué hacen exactamente y así crear unas similares para delphi.
O por lo menos, si supiésemos cómo empaqueta esos números.

newtron
25-05-2012, 17:27:27
Será mucho pedir preguntar si tienes el código fuente de esas funciones cvi/cvs mki/mks :)
Para saber qué hacen exactamente y así crear unas similares para delphi.
O por lo menos, si supiésemos cómo empaqueta esos números.

Ni de coña, eso son funciones internas del basic. La idea era que como bien sabes en aquellos tiempos había problemas de espacio en disco un número grande se podía almacenar en un campo de 4 dígitos empaquetándolo con la instrucción MKS$ y luego lo que se hacía era que cogías la parte de 4 dígitos del registro correspondiente a ese número y lo desempaquetabas con la instrucción CVD.

A ver si algún amable (y senior) forero que haya programado con versiones antiguas de basic le suena esto y me puede dar norte, si no, tendré que preparar un programita en basic que lea ese fichero, desempaquete los datos y me vaya generando otro con los números en modo carácter.

Gracias y un saludo

Casimiro Notevi
25-05-2012, 18:30:33
¿Entonces son 4 dígitos y lo que hay almacenado es un número con decimales?.

newtron
25-05-2012, 18:37:12
¿Entonces son 4 dígitos y lo que hay almacenado es un número con decimales?.

Ahimaspillao, recuerdo que se almacenaban dos tipos de números, uno en 4 dígitos y otro en 8, no recuerdo las características de cada uno.