Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 08-11-2007
JosepZ JosepZ is offline
Miembro
 
Registrado: oct 2007
Posts: 20
Poder: 0
JosepZ Va por buen camino
Cargar array of char de un archivo binario

Tengo que mostrar los datos de un archivo binario, del cual conozco su estructura, en un memo.

Todo funciona bien hasta que tengo que mostrar un dato de tipo array of char de 34 bytes, en ese momento en el memo se carga una linea vacía.

Utilizo este código:

---------Declaracion del tipo-------------
Type Tpgmf = record
//Header block
fileprint:smallint;
version:smallint;
count:integer;
//Info Block
Blockfingerprint:smallint;
BlockVersion:smallint;
RecordCount:integer;
RecordSize:integer;
//General info block
Checksum:Longword;
CourseName:string[34]; <----Uso esta para el char de 34bytes
....

var
Form1: TForm;
archivo:file of Tpgmf;

...

-------lectura del archivo y escritura en el memo------

procedure TForm1.Button1Click(Sender: TObject);
begin
if opendialog1.execute then
begin
assignfile(archivo,opendialog1.filename);
filemode:=FMOpenRead;
Reset(archivo);
Read(archivo, pgmf);
Memo1.lines.add('fileprint:'+inttostr(pgmf.fileprint));
Memo1.lines.add('Version:'+inttostr(pgmf.version));
Memo1.lines.add('Count:'+inttostr(pgmf.count));
Memo1.lines.add('Blockfingerprint:'+inttostr(pgmf.Blockfingerprint));
Memo1.lines.add('BlockVersion:'+inttostr(pgmf.BlockVersion));
Memo1.lines.add('RecordCount:'+inttostr(pgmf.RecordCount));
Memo1.lines.add('RecordSize:'+inttostr((pgmf.RecordSize)));
Memo1.lines.add('CheckSum:'+currtostr(pgmf.CheckSum));
Memo1.lines.add('CourseName:'+pgmf.CourseName); <--- Esta me pone la linea vacía

...

¿Que estoy haciendo mal?¿Cual es la forma correcta de hacerlo?

Gracias
Responder Con Cita
  #2  
Antiguo 10-11-2007
JosepZ JosepZ is offline
Miembro
 
Registrado: oct 2007
Posts: 20
Poder: 0
JosepZ Va por buen camino
Solucion y otro problema

Conseguí mostrar el array of char (eran unicode) mediante array of widechar y todo funciona bien, pero no sé por que motivo el texto se muestra bien en el memo, pero el dato que viene detrás, un integer, ya no.

Esta es la estructura del archivo a leer:

Field Offset bytes) Size (bytes) .NET Type

FileFingerprint 0 2 Int16
FileVersion 2 2 Int16
BlockCount 4 4 Int32
BlockFingerprint 0 2 Int16
BlockVersion 2 2 Int16
RecordCount 4 4 Int32
RecordSize 8 4 Int32
CheckSum 0 4 UInt32
CourseName 4 34 char[34]Unicode
WattSlopePulse 38 4 Int32<--------Este es el que se muestra incorrecto

Este es el código que uso ahora para definir los tipos

type

Tpgmf = record
fileprint:smallint;
version:smallint;
count:integer;
Blockfingerprint:smallint;
BlockVersion:smallint;
RecordCount:integer;
RecordSize:integer;
Checksum:Longword;
CourseName:array [0..17] of widechar;
WattsSlopePulse:integer;
............ .................
archivo:file of Tpgmf;
...............................................

Y este el codigo para leer del archivo y mostrar en el memo:

var CN:string;i:integer;
begin
if opendialog1.execute then
begin
assignfile(archivo,opendialog1.filename);
filemode:=FMOpenRead;
Reset(archivo);
Read(archivo, pgmf);
For i:=0 to length(pgmf.coursename)-1 do
begin
Cn:=cn+ pgmf.Coursename[i];
end;
Memo1.lines.add('fileprint:'+inttostr(pgmf.fileprint));
Memo1.lines.add('Version:'+inttostr(pgmf.version));
Memo1.lines.add('Count:'+inttostr(pgmf.count));
Memo1.lines.add('Blockfingerprint:'+inttostr(pgmf.Blockfingerprint));
Memo1.lines.add('BlockVersion:'+inttostr(pgmf.BlockVersion));
Memo1.lines.add('RecordCount:'+inttostr(pgmf.RecordCount));
Memo1.lines.add('RecordSize:'+inttostr((pgmf.RecordSize)));
Memo1.lines.add('CheckSum:'+currtostr(pgmf.CheckSum));
Memo1.lines.add('CourseName:'+cn);
Memo1.lines.add('WatSlopePulse:'+inttostr((pgmf.WattsSlopePulse)));<---Este muestra el valor incorrecto.


¿Que puedo estar haciendo mal ahora?
¿Por favor, alguien puede echarme un cable?
Gracias
Responder Con Cita
  #3  
Antiguo 10-11-2007
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
Bueno, cuando utilizabas array of char, le dabas un tamaño de 34 bytes, pero ahora, con Unicode, le están dando un tamaño de 36 bytes. ¿Puede ser debido a eso? Yo lo comprobaría, la matriz WideChar tendría que tener un elemento menos [0..16] ó [1..17]

Saludos
.
Responder Con Cita
  #4  
Antiguo 11-11-2007
JosepZ JosepZ is offline
Miembro
 
Registrado: oct 2007
Posts: 20
Poder: 0
JosepZ Va por buen camino
Gracias por la respuesta

Lo he probado y sigue pasando lo mismo.... y el caso es que si trato el archivo como si no conociera su formato y me desplazo hasta el offset siguiente al final del array of char con seek y leo los 4 bytes del integer siguiente, lo lee sin problemas y lo añade al memo...

Cada vez estoy mas confuso...
Responder Con Cita
  #5  
Antiguo 12-11-2007
JosepZ JosepZ is offline
Miembro
 
Registrado: oct 2007
Posts: 20
Poder: 0
JosepZ Va por buen camino
Ya sé cual es el problema, solucionarlo NO

He descubierto que si declaro el tipo como array of char no acabo en el offset que empieza el integer; por eso así no lo mostraba bien, y con seek(archivo,offset) si. El integer empieza en el offset 58.

Empiezo en el offset 24, y debería acabar en el 57.

Si lo declaro como array[1..33] of char acabo en el offset 56, y si lo declaro array[1..34] of char, acabo en el 60.

¿Que tamaño o tipo tendría que darle para que ocupe exactamente los 34 bytes qye tiene asignados para ese texto Unicode?
Responder Con Cita
  #6  
Antiguo 12-11-2007
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
¿?

En un principio [1..34]of char ó [1..17]of widechar tendrían que colocarte en el 57. Es realmente extraño.
Se me ocurre que, para salir del paso, podrías leer el fichero como secuencia de SmallInts o Word (Int16), ya que:

- para los datos Int16 ya lo tienes.
- para hallar los Int32, tendrías que pasar dos Int16 a hexadecimal, juntarlos, y calcular el Int32.
- cada carácter Unicode equivale a un Int16.

Es una idea, pero tu código debería funcionar. ¿Sería mucho pedir un archivo de ejemplo para que pudiéramos hacer pruebas? Con un ejemplo de lo que se debería obtener de él, claro.

Saludos.
Responder Con Cita
  #7  
Antiguo 12-11-2007
JosepZ JosepZ is offline
Miembro
 
Registrado: oct 2007
Posts: 20
Poder: 0
JosepZ Va por buen camino
¿Mucho pedir???

Al contrario, muy muy agradecido por tu ayuda.
Lo he subido aqui: http://rapidshare.com/files/69149915/FEI_004.pgmf.html

Su estructura es esta:

Field-----------------Size (bytes)--------------Type-----------------------------------Contenido en el archivo

FileFingerprint------------2---------------------Int16-------------------------------------- 1000
FileVersion---------------2---------------------Int16-------------------------------------- 100
BlockCount--------------4--------------------- Int32-------------------------------------- 2
BlockFingerprint----------2---------------------Int16--------------------------------------1010
BlockVersion-------------2---------------------Int16-------------------------------------- 100
RecordCount------------4----------------------Int32-------------------------------------- 1
RecordSize--------------4----------------------Int32--------------------------------------70
CheckSum--------------4----------------------UInt32--------------------------------------3120033703
CourseName-----------34----------------------char[34]Unicode <--Este es el problematico ---'FEI 004'
WattSlopePulse---------4----------------------Int32<-------------------------------------- 1

Con un editor hexa he comprobado que el string unicode empieza en el offset 24, exactanente donde debería teniendo en cuenta el tamaño de los tipos anteriores, y acaba en el 57; en el 58 empieza el integer que vá detrás, y con el filemon, compruebo donde acaba el array of char según su tamaño.

El texto que contiene coincide, en este caso con el del archivo, FEI 004, en unicode.

Gracias

Última edición por JosepZ fecha: 12-11-2007 a las 10:54:29.
Responder Con Cita
  #8  
Antiguo 12-11-2007
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
Hola.

Bueno, es bastante curioso lo que te pasa. Yo implementé este código:

Código Delphi [-]
program leer;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

type

Tpgmf = record
  FilePrint: SmallInt; // 2B
  Version: SmallInt; // 2B
  Count: Integer; // 4B
  BlockFingerPrint: SmallInt; // 2B
  BlockVersion: SmallInt; // 2B
  RecordCount: Integer; // 4B
  RecordSize: Integer; // 4B
  Checksum: Integer; // 4B - Uso Delphi 3 standar y LongWord no me lo reconoce 
  CourseName: array [0..16] of WideChar; // 34B
  WattsSlopePulse: Integer; // 4B
 end;

const
  TAB=#9;

var
  F: File of Tpgmf;
  Dato: Tpgmf;
  Fw: File of Byte;
  W: Byte;
  N: Integer;

begin
  AssignFile(F, ParamStr(1));
  Reset(F);
  Seek(F, 0);
  Read(F, Dato);
  CloseFile(F);
  WriteLn('FilePrint: '+IntToStr(Dato.FilePrint));
  WriteLn('Version: '+IntToStr(Dato.Version));
  WriteLn('Count: '+IntToStr(Dato.Count));
  WriteLn('BlockFingerPrint: '+IntToStr(Dato.BlockFingerPrint));
  WriteLn('BlockVersion: '+IntToStr(Dato.BlockVersion));
  WriteLn('RecordCount: '+IntToStr(Dato.RecordCount));
  WriteLn('CheckSum: '+IntToStr(Dato.CheckSum));
  WriteLn('CouseName: '+String(Dato.CourseName));
  WriteLn('WattsSlopePulse: '+IntToStr(Dato.WattsSlopePulse)+#13#13);
  ReadLn;
  AssignFile(Fw, ParamStr(1));
  Reset(Fw);
//  For N:=0 to FileSize(Fw)-1 do   Esto leería todos los bytes
  For N:=0 to 61 do  //Pero conque lea 62 está bien, es lo que ocupa la estructura
    begin
    Seek(Fw, N);
    Read(Fw, W);
    WriteLn(IntToStr(W)+TAB+IntToHex(W,2)+TAB+Chr(W));
    end;
  CloseFile(Fw);
  ReadLn;
end.

La segunda parte era para ver el balor de los bytes. Efectivamente, después de la cadena de texto (que declaras demasiado larga, tienes que quitarle un carácter, 0..17 son 36 bytes) hay un byte que vale "1", pero que leyéndolo con la estructura no aparece. Me parece que habrá que buscar otra solución (o un buen porqué).

¡Ah! y si encuentras/has encontrado la solución, postéala, no me dejes con las ganas de saber qué pasaba


Saludos.
Responder Con Cita
  #9  
Antiguo 12-11-2007
JosepZ JosepZ is offline
Miembro
 
Registrado: oct 2007
Posts: 20
Poder: 0
JosepZ Va por buen camino
El byte de valor "1" no aparece por que array[0..16] of widechar lee 36 bytes, en vez de 34, y el integer "WattsSopePulse" se desplaza.

Lo he comprobado con el file monitor;empieza a leer en el offset 0 y lee 60 bytes, dos por encima del offset 58, donde empieza el integer.

Ni idea de por que, pero lo hace. Por eso con seek, le das el offset y el tamaño y lo lee sin problemas.
Responder Con Cita
  #10  
Antiguo 12-11-2007
Avatar de ixMike
ixMike ixMike is offline
Miembro
 
Registrado: feb 2004
Posts: 1.151
Poder: 22
ixMike Va por buen camino
Me dejas de piedra.


Esto es como aquella división que me puse de pequeño y no fui capaz de resolver (con un número no llegaba, y con el siguiente me pasaba ).

¿Controlas algún otro entorno a parte de Delphi? Creo que sería buena idea probar, incluso hacerse una librería (DLL) para leer el dichoso archivo. Aún me faltan unas pocas lecciones de C, pero si llego pronto igual puedo probar.

De verdad no se me ocurre nada más.

Saludos extraños.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Cargar archivo y guardarlo en tabla Carliviris Varios 4 30-09-2006 00:39:43
cargar archivo este si gulder API de Windows 12 04-05-2005 06:26:21
cargar un archivo sys en builder israelgs C++ Builder 0 08-10-2004 21:25:32
Cargar Archivo srangel JAVA 0 03-09-2004 21:19:15
Cargar archivo chm esocrates Varios 1 27-07-2003 09:58:02


La franja horaria es GMT +2. Ahora son las 10:21:59.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi