Ayuda con codigo delfis a java

Comenzare por el principio…. Tengo la necesidad de leer un fichero binario con extensión “.oam”. Mi tarea consiste en importar ese fichero (que crea un software realizado en delfis para controlar observaciones meteorológicas), leerlo y pasar toda esa información a una base de datos para utilizarlo en otro sistema.

Yo cuento con todo el código delfis del programa que crea el fichero. Necesito que me ayuden a entender cómo funciona para poder pasarlo a java. Mando algunos trozos de códigos de lo que he entendido yo y posteriormente te mandare el código completo si es que pueden ayudarme.

Este es el código que escribe el fichero:

function Save_Data(dat_path: string): boolean;
var
F: file;
begin
try
AssignFile(F, dat_path);
Rewrite(F, 1);
BlockWrite(F, measur, SizeOf(measur));
BlockWrite(F, fix, SizeOf(fix));
BlockWrite(F, dat_a, SizeOf(dat_a));
CloseFile(F);
except
on EInOutError do
begin
case IOResult of
MessageDlg('El fichero de correcciones de datos no existe.', mtError, [mbOk], 0);
MessageDlg('No se encuentra el directorio del fichero de datos.', mtError, [mbOk], 0);
 MessageDlg('Acceso denegado para abrir el fichero de datos.', mtError, [mbOk], 0);
 MessageDlg('Error al abrir el fichero de datos.', mtError, [mbOk], 0);
end;
result := FALSE;
end;
end;
result := TRUE;
end;

Y este el que lo lee:

function Read_Data(dat_path: string): boolean;
var
F: file;
begin
try
AssignFile(F, dat_path);
Reset(F, 1);
BlockRead(F, measur, SizeOf(measur));
BlockRead(F, fix, SizeOf(fix));
BlockRead(F, dat_a, SizeOf(dat_a));
CloseFile(F);
except
on EInOutError do
begin
case IOResult of
 MessageDlg('El fichero de datos no existe.', mtError, [mbOk], 0);
 MessageDlg('No se encuentra el directorio del fichero de datos.', mtError, [mbOk], 0);
 MessageDlg('Acceso denegado para abrir el fichero de datos.', mtError, [mbOk], 0);
 MessageDlg('Error al abrir el fichero de datos.', mtError, [mbOk], 0);
end;
result := FALSE;
end;
end;
result := TRUE;
end;

las variables measure, fix y dat_a son:

measur: array[0..12, 0..3] of byte;
Arreglo bidimencional para controlar las mediciones realizadas. Cada subíndice del arreglo corresponde a una hora desde las 05 hasta las 19.
Valores que puede tomar la variable: measur
         |----------- Estado de la observación:
         |               0 - medición sin realizar por la hora
         |               1 - medición no realizada por fenómeno atmosférico (Fenómenos)
         |               2 - medición no realizada por otras causas (Nota)
         |                3 - medición realizada
         |   |-------- Actinometro: 0 No Activo (FALSE)
         |   |                            1 Activo (TRUE)
         |   |   |----- Piranometro: 0 No Activo (FALSE)
         |   |   |                         1  Activo (TRUE)
         |   |   |   | ---- Balanzometro: 0 No Activo (FALSE)
         |   |   |   |                            1 Activo (TRUE)
0 --> #, #, #, #          Los subindices
   | .                         corresponden a
  < .                         los horarios
   | .                         desde las 05
15 --> #, #, #, #         hasta las 19

fix: fix_rec; Factores de conversión de los instrumentos
fix_rec = record // Datos fijos para un día de observación
   est_code: word; // Código de la estación INCLUIR PARA EL NUEVO REPROCESAMIENTO
   mdate, // Fecha de la medición
   fc_acti, // Factor de conversion del Actinometro
   fc_pira, // Factor de conversion del Piranómetro
   fc_balan: single; // Factor de conversion del Balanzómetro
end;

dat_a: act_array; // Arreglo con los datos de la medición (Iniciales, Lecturas y Resultados)
act_array = array[0..12] of act_rec;
act_rec = record // Estructura de los datos de una medición
     hini, // Hora de inicio de la medición
     hfin, // Hora final de la medición
     ho, // Altura del sol
     seno_ho, // Seno de la altura del sol
     delta_tau, // Delta TAU
     declina, // Declinación
     solar_time: double; // Tiempo solar o tiempo real
     tnubes, // Total de nubes
     nbajas, // Total de nubes bajas
     cu, // Tipo de nube - Cumulos
     cb, // Tipo de nube - Cumulos Nimbos
     sc, // Tipo de nube - Estratos Cumulos
     st, // Tipo de nube - Estratos
     ac, // Tipo de nube - Altos Cumulos
     ae, // Tipo de nube - Altos Estratos
     ns, // Tipo de nube - Nimbo Estratos
     ci, // Tipo de nube - Cirros
     cs, // Tipo de nube - Cirros Estratos
     cc, // Tipo de nube - Cirros Cumulos
     ccielo, // Color del cielo
               // 0 - No se reporta
               // 1 - Azul
               // 2 - Azul Claro
               // 3 - Blanquecino
     dsolar, // Estado del disco solar
               // 0 - Sol cuadrado
               // 1 - Sol
               // 2 - Sol con grado
               // 3 - Sol cubierto (P rusa)
               // 4 - Sol Obstruido (no natural)
     visib, // Visibilidad
     mhierba, // Madurez de la hierba
                  // 0 - Verde
                  // 1 - Amarilla
                  // 2 - Seca
     hhierba: byte; // Humedad de la hierba
                           // 0 - Seca
                           // 1 - Humeda
                           // 2 - Anegada
     taires, // Temperatura del aire seca
     taireh, // Temperatura del aire humeda
     tsuelo: single; // Temperatura del la superficie activa
     tactin: lec_array; // Temperatura para ajuste del actinómetro
     humed: byte; // Humedad Relativa del aire
     ajacti, // Ajuste del cero - actinómetro
     ajbalan, // Ajuste del cero - Balanzómetro
     ajpira, // Ajuste del cero - Piranómetro
     fc_temp: single; // Factor de conversion por temperatura del Actinómetro
     fenom: byte; // Fenómenos atmosféricos
              // 0: No hay
              // 1: Rocio
              // 2: Bruma
              // 3: Niebla
              // 4: Neblina
              // 5: Humo
              // 6: Chubascos
              // 7: Lluvia
              // 8: Tormenta con Precipitacion
              // 9: Tormenta sin precipitacion
              //note, // Notas
      note: ShortString; // Notas
      observ: obs_array; // Nombre del observador
      num_obs: word; // Numero del Observador
          // LECTURAS DE LOS INSTRUMENTOS
       P_D1, // Piranómetro (D1)
       B_B, // Balanzómetro (B)
       B_BS, // Balanzómetro (B-S')
       P_Q, // Piranómetro (Q)
       P_RC, // Piranómetro (Rc)
       P_D2, // Piranómetro (D2)
       BV_B, // Velocidad del viento (B)
       BV_BS: lec_array; // Velocidad del viento (B-S')
       A_D1, // Actinómetro (D1)
       A_B, // Actinómetro (B)
       A_BS, // Actinómetro (B-S')
       A_Q, // Actinómetro (Q)
       A_RC, // Actinómetro (Rc)
       A_D2: single; // Actinómetro (D2)
      dn: dn_rec; // Correciones de los instrumentos
      nr: nr_rec; // Resultados intermedios
      opv: opv_rec; // Resultados del procesamiento
end;

Si me pudieran ayudar estaría muy agradecido….

Gracias de antemano.

Este es mi correo yusnier.acosta@reduc.edu.cu

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

"delfis"?

Será Delphi a lo que te refieres? Necesitas una referencia de Delphi para ver la compatibilidad entre tipos de datos, a ver cómo se guarda un boolean, un byte, enteros, etc. Desde Java tendrás que leer por puro byte porque por lo que veo, en Delphi se escribe el archivo pensando que solamente se va a leer con Delphi mismo, no es un formato precisamente portable.

Imagen de changa

Entonces tendría que leer el

Entonces tendría que leer el fichero como bytes y tratar de convertirlos a los datos equivalentes en java? seria posible realizarlo desde java, una ves aya entendido la estructura en delphis?

Imagen de ezamudio

claro

Por ejemplo si sabes que tienes un entero sin signo, de dos bytes, entonces lees 2 bytes del archivo y luego:

int x = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
//Para 4 bytes
x = ((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) | ((buf[2] & 0xff) << 8) | (buf[3] & 0xff);

Sospecho que te van a dar más lata las cadenas, porque tendrás que averiguar cómo las maneja Delphi. Si mal no recuerdo, son tipo Pascal, o sea que primero llevan uno o dos bytes indicando la longitud de la cadena y luego lees ese número de bytes para obtenerla (y con eso en Java creas un String y listo). Y si tienes números de punto flotante también le vas a sufrir con eso un poco.

Imagen de changa

Que puedo hacer??

Esta es la situación, debo realizar un sistema web que sea capaz de leer esos ficheros y pasarlos a una base de datos…. Yo pensé en java pues es el lenguaje que dominio, pero si decidiera realizar el sistema con PHP y esta parte de la lectura del binario con cualquier otro lenguaje que me corra del lado del servidor, que me sugerirías; o si debo orientar mi objetivo asía otro lenguaje y de otra forma? Me seria más productivo… no interesa que tenga que estudiar otros lenguajes, sería como parte de mi superación antes de graduarme..

Imagen de ezamudio

Sólo Delphi

Quien hizo el código para crear esos archivos tal vez no había oído hablar nunca del concepto de portabilidad, y por eso usó un formato que solamente es fácilmente legible desde Delphi. Así que vas a tener la misma bronca para leerlo en Java, C, PHP, Groovy, Ruby, Python, etc.

La solución sigue siendo la misma: investiga cómo se almacenan los datos en Delphi. Si tienes a la mano el IDE o como se llame de Delphi, haz un pequeño programa (basado en el código que pusiste aquí) donde generes un archivo que solamente almacena un entero, otro que solamente almacena un flotante, otro que solamente almacena una cadena, etc. Y así los puedes analizar desde fuera (con hexdump o algo similar) y saber cómo leer los datos.

Imagen de changa

OK

Crasis por tus consejos.
Esto es lo que he hecho. El fichero está estructurado de 36 a 39 bloques, cada bloque corresponde a una variable declarada en el delphi que se repite cada tres bloques, o se:

variable 1
variable 2
variable 3
variable 1
.
.
.
.
variable 3
lo que haré es utilizando el mismo código delphi que me proporcionaron para realizar llamadas a la función “SizeOf()” que me devuelve la cantidad de bytes utilizados por esta variable, de esa forma conozco la longitud de cada una y puedo realizar la lectura desde java y cotejarlo con su valor correspondiente…Corrígeme si estoy mal..
nuevamente gracias…

Imagen de ezamudio

bien

Suena bien lo que piensas hacer. Con eso tendrás los tamaños de cada dato. Solamente falta ver cómo se almacena cada dato (si es un entero con signo o sin signo, si está "normal" usando complemento a dos en caso de ser con signo, etc).

Imagen de changa

ok

Gracias por tu ayuda…trabajare en esa línea y te comento luego..

Imagen de changa

Avanzando…

Ya logro leer una parte…estoy trabado en leer una variable de tipo “single” que al parecer es equivalente al float, pero no obtengo el resultado esperado…
Todo lo estoy realizando con la clase “RandomAccessFile” y he logrado leer las primeras variables que han correspondido con array de “byte” y “short”, pero no logro esta de tipo “single”. No sé si es que ese no es su equivalente o si estoy leyendo con el método equivocado (readFloat())….

Imagen de ezamudio

RAF?

Necesitas de verdad RandomAccessFile? Esa clase es útil cuando necesitas estar cambiando de posiciones dentro de un archivo, de manera arbitraria; si estás importando datos del archivo de Delphi, con un InputStream normal debería bastar, no? O hay algun caso en que por algun dato que lees, tienes que regresar a una parte anterior del archivo?

El tipo Single me recuerda a Pascal (bueno creo que Delphi se basa en Pascal de hecho). Había Single y Double, y tienen distinta precisión. Creo que en Java el equivalente sería Float (porque tenemos Double además) pero la verdad quién sabe.

Imagen de changa

En eso

Escogí esa clase porque quiero saltarme algunos byte que no deseo leer…. Lo de la variable “single” ya lo encontré, pensé que era equivalente al float al igual que tu, pero resulta ser que lo que almacena esa variable es 8 dígitos (letras y números) y no encuentro ningún equivalente. Entonces no sé como leerla, ni la cantidad de byte que ocupa…

Imagen de ezamudio

8

No será que ocupa 8 bytes entonces? O puede almacenar 8 caracteres Unicode?

La manera de saber cómo se guarda y cuánto espacio ocupa es que desde Delphi generes un archivo donde solamente guardes un dato de ese tipo (de hecho que hagas varios archivos, cada uno con un dato de ese tipo, ocupando distintos valores). Es ingeniería reversa básica.

Para saltarte bytes con un InputStream se usa el método skip(long) con eso te saltas bytes (pero con un stream ya no puedes regresar a una posición previa).

Imagen de changa

Ya

Ya la encontré, el single utiliza 4 byte o lo que es lo mismo 32 bits, pero el problema que me daba al leerlo y tratar de convertirlo en un float era que como el acepta caracteres y números… veré ahora como lo leo… si tienes alguna idea…

Imagen de changa

single

Tipo:Single
Rango de valores:1.5 x 10^-45 a 3.4 x 10^38
4 byte
Detalle:Coma flotante, 7-8 dígitos significativos

Imagen de ezamudio

Single

Entonces no acepta letras y números, solamente valores numéricos. Si dices que acepta letras porque imprimiste los 4 bytes en consola como si fueran una cadena, es obvio que de repente aparecerán letras, porque uno de los 4 bytes tiene un valor entre 65 y 126. Pero eso no significa que el tipo de dato sea alfanumérico. Ahora la cosa es, cómo vas a convertir esos 4 bytes de single, en un Float.

Imagen de changa

Terminado

Ya tengo todo casi terminado, solo me falta realisar una pequena combercion de doublea fecha utilisando el mismo metodo que esta en delphis (pasandolo a java), y lo mismo con otros resultados que son tratadosde manera espesial en el aniguo programa....
Muchas crasias por tu ayuda, estoy super agradesido con tus aportes....
Saludos...
PD: despues publicare el codigo de lo que tengo echo por si algien esta en la misma situasion que yo