Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > C++ Builder
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 22-11-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Leer DWORDs invertidos

Hola amigos, cuando se lee un int de un archivo binario se pasa al int invertido, osea que si en el archivo vemos 21 33 55 44 y leo esa memoria a un int se pasa como 0x44553321. La cuestion es que quiero leerlo como 0x21335544 y no tengo ni idea de como hacer eso. ¿alguien sabria ayudarme?
Responder Con Cita
  #2  
Antiguo 23-11-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por aguml Ver Mensaje
Hola amigos, cuando se lee un int de un archivo binario se pasa al int invertido, osea que si en el archivo vemos 21 33 55 44 y leo esa memoria a un int se pasa como 0x44553321. La cuestion es que quiero leerlo como 0x21335544 y no tengo ni idea de como hacer eso. ¿alguien sabria ayudarme?
Eso no siempre es así, depende de la arquitectura del procesador. Me temo que tendrás que cambiar las posiciones a mano, o leer byte a byte. El problema lo vas a tener en los cast por lo que tendrás que pensar bien que quieres hacer, porqué, como y cuando.

Saludos
Responder Con Cita
  #3  
Antiguo 23-11-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Se me ocurre algo así:
Código PHP:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
    
int valor=0x12345678;
    
int i;
    
char cadena[11];
    
char aux[3];
    
sprintf(cadena,"0x%X",valor);
    
printf("%s\n",cadena);
    for(
i=2;i<6;i+=2){
        
strncpy(aux,&cadena[i],2);
        
strncpy(&cadena[i],&cadena[8-(i-2)], 2);
        
strncpy(&cadena[8-(i-2)],aux,2);
    }
    
printf("%s\n",cadena);
    
valor=atoi(cadena);
    
printf("%x\n",valor);
    return 
0;

Solo que atoi no me devuelve un valor bueno aunque quiero hacerlo con AnsiString y tiene su método ToInt() y podría usar SubString en lugar de strncpy pero tengo que ver cómo adaptarlo. El fallo que veo es que trabajar con strings es lento en comparación con trabajar con números.
Otra opción que se me ocurre es leer del fichero 4 bytes como char[4] y luego convertir con algún Cast esos 4 bytes en un entero ¿Con eso obtendría el valor invertido? ¿Cómo se haría ese Cast?
Responder Con Cita
  #4  
Antiguo 23-11-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
No entiendo que tengas que usar cambios a cadenas de caracteres, ¿Te interesan los datos en caracteres o numéricos?

Saludos.
Responder Con Cita
  #5  
Antiguo 23-11-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
A ver si me explico, este archivo es leido por la PS3 y es donde se guarda la partida de un juego en concreto. La empresa que ha creado el juego lo ha protegido con un checksum que por lo visto se llama DWADD que no es mas que ir sumando DWORDs del archivo uno detras de otro en un rango especifico y el valor obtenido es el checksum el cual lo guarda en otra parte del archivo para saber si ha sido modificado. El problema me lo encontré con que mi checksum no tenia nada que ver con el correcto y despues de muchas vueltas alguien me dijo que el modo en que se lee la memoria depende de la arquitectura del procesador y me dije ¿y si la ps3 lo hace al reves?
O sea, si miras en binario el archivo verias algo como
11 22 33 44 55 66 77 88
Si lees dos dwords obtendrias:
0x44332211
0x88776655
Al menos en mi pc es asi.
Pues bien, la suma al final si que era invirtiendolo con lo que quedarian como:
0x11223344
0x55667788
Lo he conseguido con esta pequeña funcion que me he creado para esto:
Código PHP:
int TForm1::InvertirValor(int valor)
{
    
union{
        
int valor;
        
unsigned char cadena[5];
    }
u;
    
int aux;

    
u.valor=valor;

    
aux u.cadena[0];
    
u.cadena[0]=u.cadena[3];
    
u.cadena[3]=aux;

    
aux=u.cadena[1];
    
u.cadena[1]=u.cadena[2];
    
u.cadena[2]=aux;

    return 
u.valor;
}
//--------------------------------------------------------------------------- 
Con eso consigo lo que quiero, primero invirtiendo cada DWORD que leo y luego, antes de guardar el checksum en el archivo invierto tambien el checksum para que se guarde correctamente y con eso va perfecto.
De todos modos soy todo oidos.
Responder Con Cita
  #6  
Antiguo 23-11-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Si, esa puede ser una forma de hacerlo pero en la unión que usas, la parte de cadena deben ser 4 uchar y no 5 que son 32 bits, el tamaño de int.

Otra forma es usar funciones que ya tenemos disponibles como htonl de la librería Winsock2 y que está disañada para compatibilizar los sistemas en red (Little Endian a Big Endian)


Saludos.

Última edición por escafandra fecha: 23-11-2017 a las 14:52:43.
Responder Con Cita
  #7  
Antiguo 24-11-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
¿Podrías poner algún ejemplo de uso de htonl?
No lo había escuchado nunca pero la verdad es que para algo tan trivial tener que añadir toda una librería...
Una duda que tengo es si podría hacerlo de otra manera que sería leer, con la misma unión pero usando la cadena, directamente con FileRead cogiendo como cadena de 4 bytes y al leer el int que hay en la unión ya estaría invertido o tendría que invertirlo igualmente.
Responder Con Cita
  #8  
Antiguo 24-11-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por aguml Ver Mensaje
¿Podrías poner algún ejemplo de uso de htonl?
No lo había escuchado nunca pero la verdad es que para algo tan trivial tener que añadir toda una librería...
Realmente solo debes incluir el archivo cabera Winsock2.h y usar htonl normalmente. Convierte un ulong (DWORD) Little Endian a Big Endian.
Código PHP:
DWORD htonl(DWORD little); 
Cita:
Empezado por aguml Ver Mensaje
Una duda que tengo es si podría hacerlo de otra manera que sería leer, con la misma unión pero usando la cadena, directamente con FileRead cogiendo como cadena de 4 bytes y al leer el int que hay en la unión ya estaría invertido o tendría que invertirlo igualmente.
Eso no funciona, el procesador siempre interpretará lo mismo.


Saludos.
Responder Con Cita
  #9  
Antiguo 27-11-2017
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Ok gracias.
Responder Con Cita
  #10  
Antiguo 29-11-2017
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Digo yo que leer byte a byte y usar operadores de bit funcionará, ¿no?

A ver si me acuerdo de cómo era la cosa esta:
[edito] He releido la pregunta:
Código:
  int i;
  long Valor;
  FILE *ElArchivo;

  for (i = 0, Valor = 0; i < 4; ++i)
    Valor = (Valor << 8) | (getc (ElArchivo) & 0x000000FF);
Era así, ¿no?
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #11  
Antiguo 30-11-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por Ñuño Martínez Ver Mensaje
Digo yo que leer byte a byte y usar operadores de bit funcionará, ¿no?

A ver si me acuerdo de cómo era la cosa esta:
[edito] He releido la pregunta:
Código:
  int i;
  long Valor;
  FILE *ElArchivo;

  for (i = 0, Valor = 0; i < 4; ++i)
    Valor = (Valor << 8) | (getc (ElArchivo) & 0x000000FF);
Era así, ¿no?
Falta abrir el archivo (fopen), supongo que es omisión deliberada. El trabajo con desplazamiento de bits claro que funciona.

Saludos.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

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
Leer CSV Willo Varios 4 04-04-2017 21:06:21
Leer XML chinchan C++ Builder 3 09-11-2012 00:45:24
Leer XML cmm07 Varios 4 02-02-2010 15:36:05
Leer *.res dmagui Varios 5 04-10-2005 23:40:32
Leer usb trex2000 Varios 1 14-03-2005 13:51:41


La franja horaria es GMT +2. Ahora son las 22:34:31.


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