Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Comparar cadenas de caracteres sacadas de un fichero (https://www.clubdelphi.com/foros/showthread.php?t=38638)

papulo 21-12-2006 11:08:19

Comparar cadenas de caracteres sacadas de un fichero
 
Estoy intentando procesar un fichero que no lo puedo leer como texto.

La información que me interesa comienza siempre con la misma cadena, 00:F5:02:40:00 en hexadecimal.

El código que uso es el siguiente:
Código Delphi [-]
  try
    BlockRead(ffile_input, Ch, 1); //Leo un caracter y lo guardo en 'Ch'
  except
    exit
  end;
  buffer := ''; //Reseteo el Buffer
  sStartCross := Chr(0) + Chr(245) + Chr(2) + Chr(64) + Chr(0); //Inicio la marca de comienzo de los datos

  repeat
    if Length(buffer) < 5 then //Consigo la longitud mínima para la comparación
      begin
        BlockRead(ffile_input, Ch, 1);
        buffer := buffer + Chr(Ch);
      end
    else
      begin
        BlockRead(ffile_input, Ch, 1);
        buffer := buffer + Chr(Ch);
        buffer := AnsiRightStr(buffer, 5);
      end;
  until (StrComp(Pchar(buffer), Pchar(sStartCross)) = 0);


EL valor del sStarCross es #0'õ'#2'@'#0 y no hay forma de que en el bucle me cumpla la condición de la comparación bien.

No se por donde cogerlo, es la primera vez que tengo que hacer algo así y ahora he visto que el problema está ahí, en como comparo buffer y sStarCross , que no se cumple la condición bien.

Casimiro Notevi 21-12-2006 11:56:24

Si las variables sStartCross y buffer son de tipo strings, prueba a comparar con la función de windows: lstrcmpi que es equivalente al strcmp del lenguaje C.

Puede que te sirva.

papulo 21-12-2006 12:00:50

El error que me da si lo escribo así:

Código Delphi [-]
...  
until (StrComp (buffer, sStartCross) = 0);
es "Incompatible types: 'String' and 'PAnsiChar'"

sStarCross y Buffer son ambos 'Strings'

Me da el mismo error con la orden que me has dado.

seoane 21-12-2006 13:37:17

:confused: No se si me estoy perdiendo algo. Pero lo primero que veo es que estas utilizando el carácter #0, y recordemos que ese carácter se utiliza para marcar el final de una cadena. Por lo tanto cuando haces esto:

Código Delphi [-]
(StrComp(Pchar(buffer), Pchar(sStartCross)) = 0)

Como sStartCross comienza por #0, se considera una cadena vacía, así que en el momento en que el contenido de buffer también comience por #0 la condición se cumplirá, es decir, no se tendrán en cuenta el resto de caracteres. Yo te sugiero que para hacer comprobaciones en las que interviene el carácter #0 utilices funciones como CompareMem, mucho mas rápida, y no te metas a utilizar funciones para el tratamiento de cadenas ;)

papulo 21-12-2006 13:58:46

Cita:

Empezado por seoane
Como sStartCross comienza por #0, se considera una cadena vacía, así que en el momento en que el contenido de buffer también comience por #0 la condición se cumplirá, es decir, no se tendrán en cuenta el resto de caracteres. Yo te sugiero que para hacer comprobaciones en las que interviene el carácter #0 utilices funciones como CompareMem, mucho mas rápida, y no te metas a utilizar funciones para el tratamiento de cadenas ;)

Gracias Seoane, hace un rato que lo he averiguado :D depurando chino chano. De todas formas, ¿un ejemplo ilustrativo de código para novatos? de esos que facilitan la comprensión y me sirven para hacerme la idea y poder aplicarlo, porque todos sabemos que la ayuda de Dlphi 7 es...¿escasa y escueta? al menos para mi, de momento.

Casimiro Notevi 21-12-2006 14:08:53

Y si siempre comienza por esa cadena ¿por qué no te lo saltas y empiezas en la posición siguiente?

¿Puedes ponernos un trocito del fichero para probar?

Crandel 21-12-2006 14:26:00

siempre puedes escribir una pequenia funcion propia de comparacion, con un simple ciclo dentro que compare elemento por elemento y que te devuelva un true en caso de ser iguales.

Aunque creo haber visto dentro de delphi una funcion similar pero no recuerdo donde.

papulo 21-12-2006 14:30:03

Casimiro:
Se que podría saltarmelo y buscar la cadena 'F5:02:40:00' directamente, pero eso no resolvería mi problema, solo lo parchearía. Y si en un momento dado tengo que pelearme con cadenas cuyo identificador comienza por '00' tendré que aprender, y ya que el tema me pilla pez, mejor aprenderlo sin vicios ni malas costumbres

Aqui un trozo:

Código:

00000000:00 00 20 20 20 20 20 20 20 20 20 20 20 20 20 20    ..             
00000010:20 20 20 00 32 34 32 31 31 00 20 20 20 20 20 20      .24211.     
00000020:20 20 00 4e 45 57 20 48 4f 4c 4c 41 4e 44 00 20      .NEW HOLLAND.
00000030:20 20 20 20 20 20 20 00 33 33 33 20 54 52 41 43          .333 TRAC
00000040:54 4f 52 00 20 20 20 20 20 20 20 20 20 20 20 20    TOR.           
00000050:20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                   
00000060:20 20 20 20 20 20 20 20 20 20 00 31 39 37 35 00              .1975.
00000070:31 39 38 34 00 f5 02 40 01 00 00 00 00 00 20 20    1984.õ.@...... 
00000080:20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 00                  .
00000090:32 33 39 38 33 00 20 20 20 20 20 20 20 20 00 46    23983.        .F
000000a0:4f 52 44 00 20 20 20 20 20 20 20 20 20 20 20 20    ORD.           
000000b0:20 20 20 00 43 4f 52 54 49 4e 41 20 49 56 20 31      .CORTINA IV 1
000000c0:2c 33 20 28 4c 46 50 2d 54 4f 20 52 45 50 4c 41    ,3 (LFP-TO REPLA
000000d0:43 45 20 4c 55 43 41 53 20 4f 4e 4c 59 29 00 20    CE LUCAS ONLY).
000000e0:20 20 20 20 20 20 00 31 39 37 36 00 31 39 37 39          .1976.1979
000000f0:00 f5 02 40 01 00 00 00 00 00 20 20 20 20 20 20    .õ.@......     
00000100:20 20 20 20 20 20 20 20 20 20 20 00 32 33 39 38              .2398

Crandel:
Esa es la opción que estaba barajando y que parametrizandola me dará toda la funcionalidad que busco.

seoane 21-12-2006 14:47:25

Una primera aproximacion sería algo como esto:

Código Delphi [-]
function Buscar(Archivo: String; Sub: Pointer; Count: int64): int64;
var
  P: PByte;
  i: int64;
begin
  Result:= -1;
  with TMemoryStream.Create do
  try
    LoadFromFile(Archivo);
    if Size < Count then
      Exit;
    i:= 0;
    P:= Memory;
    while (not CompareMem(Sub,P,Count)) and (i < Size) do
    begin
      inc(P);
      inc(i);
    end;
    if i < Size then
      Result:= i;
  finally
    Free;
  end;
end;

// Por ejemplo
var
  Buffer: Array[1..6]of Byte;
begin
  Buffer[1]:= $00; Buffer[2]:= $F5; Buffer[3]:= $02;
  Buffer[4]:= $40; Buffer[5]:= $00;
  ShowMessage(IntToHex(Buscar('d:\1.dat',@Buffer,5),8));
end;

La función buscar, nos devuelve la posición de la cadena que buscamos, o -1 si no la encuentra. La única desventaja es que cargamos todo el archivo en memoria y si el archivo es muy grande (un par de decenas de megas) puede resultar un problema.

papulo 21-12-2006 14:49:53

Ostias! Eso me llevará un rato leerlo, comprenderlo y asimilarlo. Asi que aprovecho para hacer una pausita, ir al gimnasio, comer y luego con fuerzas renovadas me enfrentaré a esto.

Gracias Seoane y a todos los demás.

PD:Soluciones mas sencillas también se aceptan :D

seoane 21-12-2006 14:56:09

Cita:

Empezado por papulo
Ostias! Eso me llevará un rato leerlo, comprenderlo y asimilarlo. Asi que aprovecho para hacer una pausita, ir al gimnasio, comer y luego con fuerzas renovadas me enfrentaré a esto.

Quizá yo también tendría que ir al gimnasio, en vez de pasarme el día delante del ordenador :p :D :D

Casimiro Notevi 21-12-2006 15:50:30

Cita:

Empezado por seoane
Quizá yo también tendría que ir al gimnasio, en vez de pasarme el día delante del ordenador :p :D :D

ya somos dos :(




Por cierto, Papulo, ¿eso es una tabla de algún tipo de base de datos que quizás sea pública su estructura, no?

Crandel 21-12-2006 16:00:11

Cita:

Empezado por Casimiro Notevi
ya somos dos :(

ya somos tres :( , pero a mi por suerte recien me toca el anio que viene, voy dos meses cada dos anios :D uy no falta tanto para el anio que viene :eek: :eek: puedo esperar un anio mas... este anio no comi tantas facturas :rolleyes:

seoane 21-12-2006 16:07:39

:( Total, mucho tendría que estar en el gimnasio para ponerme como el amigo Xander que aquí parece un croasant :D (sin animo de ofender)

Aqui una fotos de un crosant para comparar
http://images.google.com/images?hl=e...-8&sa=N&tab=wi

:D :D :D

papulo 21-12-2006 17:05:29

Cita:

Empezado por Casimiro Notevi
ya somos dos :(

Por cierto, Papulo, ¿eso es una tabla de algún tipo de base de datos que quizás sea pública su estructura, no?

No es pública pero si autorizada, es del perro de uno de nuestros proveedores, que quiere aparecer en nuestro catálogo, pero los mamones se tocan las pelotillas a la hora de pasarnos la información.

No os imaginais lo descoordinadas que son las grandes empresas, BOSCH, VALEO y esta gente.

A veces da la sensación de que ves ciclopes dando palos de ciego.

A todos los demás, el ejercicio viene de fábula, yo no estoy tan cachas como el amigo bombero, pero estoy cuadradete tambien, y a parte hago esgrima y juego a balonmano. :D

Casimiro Notevi 21-12-2006 19:20:31

Si son registros de longitud fija lo tienes sencillo.

papulo 21-12-2006 19:23:25

Cita:

Empezado por Casimiro Notevi
Si son registros de longitud fija lo tienes sencillo.

Sin que sirva de precendente (dicese de algo que va antes de)...
¿Me lo expliquen?

¿Que quieres decir con eso?:confused::confused:

Casimiro Notevi 21-12-2006 20:05:47

que si el fichero es de una forma parecida a esta, tiene una cabecera y luego los registros en sí:
xx bytes -> cabecera de longitud la que sea (puede no tener cabecera)
64 bytes -> datos de un registro
64 bytes -> datos de otro registro
64 bytes -> datos de un registro más
64 bytes -> etc...

cada uno de esos 64 bytes (es un ejemplo), pueden estar subdivididos en los campos de la tabla:
08 bytes -> código
32 bytes -> descripción (es el dato que te interesa, creo)
08 bytes -> precio
xx bytes -> etc...


Si este fuese el caso tan sólo tendrías que "saltar" la cabecera y luego leer/saltar a intervalos fijos para los datos que te interesan de cada registro.

Aunque seguro que esta posibilidad ya lo habrás comprobado, era sólo por dar una idea más.

papulo 21-12-2006 22:33:04

Negativo, casimiro, no es de longitud fija.Si lo fuera sería un chollete. :D

Casimiro Notevi 21-12-2006 22:49:47

al menos podrían decirte qué tipo de archivo es :o


La franja horaria es GMT +2. Ahora son las 12:03:09.

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