Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Error con buffer (https://www.clubdelphi.com/foros/showthread.php?t=84804)

andres_89 08-12-2013 18:31:45

Error con buffer
 
Buenas amigos, tengo un pequeño error al tratar de leer un ejecutable en hexadecimal, consigo leer la parte que quiero, pero al momento de volverlo a leer se va concatenando lo que leí al principio con lo que leo segundo, y lo que quisiera es que si vuelvo a leer me borre lo leído anteriormente, les dejo el código para ver donde cometo mi error:

Código:

void file_hex()
{

    AnsiString str1,str2,hex,cadena_1,cadena_2,cadena;

    unsigned int length;
    unsigned char *buffer;
    char nombre_archivo[] = "prueba.exe";

    ifstream archivo(nombre_archivo, ios::binary);

    if(archivo.fail())
        cout << "Error al abrir el archivo " << nombre_archivo << endl;
    else
    {
        // obtener longitud del archivo
        archivo.seekg (0, ios::end);
        length = archivo.tellg();
        archivo.seekg (0, ios::beg);

        // obtener memoria para la variable
        buffer = new unsigned char [length];

        // leer datos como bloque
        archivo.read ((char*)(buffer),length);
        archivo.close();

        // imprimir cada posicion del buffer como hexadecimal
        for (unsigned int i = 200; i < 216; i++)
      //    for (unsigned int i = 384; i < 400; i++) //linea de codigo que solo quiero leer
        {
            if (buffer[i] < 16)
                {
                    str1.printf("0%X", buffer[i]);
                    strcat(cadena_1.c_str(),str1.c_str());
                }
            else
                {
                    str2.printf("%X", buffer[i]);
                    strcat(cadena_2.c_str(),str2.c_str());
                }
        }

        /*  cadena.c_str() -> se almacena toda la cadena hexadecimal


        hex = cadena.c_str();
        Form1->Edit1->Text = hex;

        delete[] buffer; // creo que acá esta el error, lo elimino pero igual se sigue quedando en el buffer.
    }
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Edit1->Clear();//supuestamente borro la cadena mostrada en edit1.
  file_hex();
}

cuando lo ejecuto me muestra la cadena hexadecimal normal, pero cuando lo vuelvo a ejecutar, me devuelve la cadena + la cadena anterior, y asi se van concatenando mientras los voy ejecutando, lo cual no quiero, quiero que si vuelvo a ejecutar me borre la anterior y me muestre solo la actual cadena ejecutada, bueno espero me hayan entendido.
gracias por las respuestas.

aguml 09-12-2013 00:00:41

veo muchas cosas raras como que los valores los almacenas en cadena 1 y cadena2 pero luego no haces uso de ellos y si de cadena el cual no le has dado ningun valor. Otra cosa, en vez de Edit1->clear, prueba Edit1->text="".

ecfisa 09-12-2013 02:02:52

Hola andres_89.

Si estás usando C++ Builder de modo visual, en lugar de usar la librería estándar ifstream, te conviene aprovechar la VCL usando TFileStream,
aquí hay algunos ejemplos: File Processing, buscando seguramente encontraras mas material.

No sé si interpreté lo que queres hacer, pero te pongo un ejemplo acorde a lo que entendí:
Código:

String file_hex(const String aFileName, const int LoPos, int HiPos)
{
  TFileStream *fs = new TFileStream(aFileName, fmOpenRead); // abrir p/lectura
  unsigned char *buff = new unsigned char[fs->Size];  // tamaño buffer
  String str = "";
  try {
    fs->Read(&buff, fs->Size-1);
    for (int i = LoPos; i <= HiPos; i++)
      str += IntToHex(buff[i], 2) + ' ';
  }
  __finally {
    delete[] buff;
    delete fs;
  }
  return str.SetLength(str.Length()-1); // quitar el último ' '
}

Ejemplo de uso, obtener en un TEdit los primeros 20 valores del archivo notepad.exe en formato hexadecimal:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Edit1->Text = file_hex("C:\\Windows\\notepad.exe", 0, 20);
}

Para simplificar el ejemplo no realicé ningún tipo de comprobación (existencia del archivo, valor de los argumentos, etc)

Saludos :)

andres_89 09-12-2013 03:36:35

Error ceros
 
Hola ecfisa,gracias por la opción al vlc, como dices mejor aprovecharla si ya se tiene,pero ejecute el código y probando con otros archivos y otras posiciones como (50,70), pero en todas me muestran :

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

, ya lo ejecute como administrador e igual me sigue mostrando ceros en cualquier posición.

Saludos.

ecfisa 09-12-2013 05:48:16

Tenes razón, disculpas.

Código:

String file_hex(const String aFileName, const int StartingAt, const int Quantity)
{
  TFileStream *fs = new TFileStream(aFileName, fmOpenRead);
  unsigned char buff;
  String str = "";
  try {
    fs->Seek(StartingAt, soFromBeginning);
    for(int i = 0; i < Quantity; i++) {
      fs->Read(&buff, 1);
      str += IntToHex(buff, 2) + ' ';
    }
  }
  __finally {
    delete fs;
  }
  return str.SetLength(str.Length()-1);
}

Uso:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Memo1->Text = file_hex("C:\\Windows\\notepad.exe", 95, 20);
}

Ahora a la función se le envían como argumentos, la posición inicial (basada en cero) y la cantidad de elementos a leer a partir de ella.

Saludos :)

escafandra 09-12-2013 21:09:24

Os propongo una función en Ansi C para convertir una cadena contenida en un buffer de tamaño conocido y no ASCIIZ (como el buffer obtenido de la lectura de un archivo de texto) en texto hexadecimal:

Código:

//---------------------------------------------------------------------------
// Convierte un buffer binario en una cadena de números hexadecimales
bool BinToStr(BYTE *Bin, DWORD BinSize, char* Str, DWORD *StrSize)
{
  if(!Str){
    *StrSize = 2*BinSize + 4; // '\0' y dos caracteres de mas para el final en "\r\n"
    return false;
  }
 
  if(*StrSize <  2*BinSize + 4) return false;
 
  for(int i=0; i<BinSize; i++){
    *Str = (0x0F & *Bin>>4) + 48;
    *(Str+1) = (0x0F & *Bin) + 48;
    if(*Str > '9') *Str += 7;
    if(*(Str+1) > '9') *(Str+1) += 7;
    Bin++; Str+=2;
  }
  *Str++ = '\r'; *Str++ = '\n'; *Str = 0;
  return true;
}

El resultado lo devuelve en otro buffer de tamaño mínimo 2*BinSize + 4
Si pasamos como argumento Str = NULL nos devuelve el tamaño del buffer necesario (2*BinSize + 4)


Es una función que yo he usado para esos fines.

Saludos.

andres_89 10-12-2013 19:11:04

Hexadecimal
 
Hola ecfisa y escafandra,

el código de ecfisa, me funciono correctamente pasandole como parámetro cualquier archivo, gracias.

escafandra, tu código lo veo muy interesante, estoy analizando tu función ("bool BinToStr(BYTE *Bin, DWORD BinSize, char* Str, DWORD *StrSize)"), sinceramente no habia visto algunos códigos del Anci C que están en tu código....., bueno, una consulta estoy tratando de llamar tu función para leer un archivo como hexadecimal pero no logro a llamarla, encontre una forma de llamarla pero no me funciona:

BINTOSTR(string, string_type)

cuales serian sus parámetros?

Saludos.

escafandra 10-12-2013 23:06:27

[code]bool BinToStr(BYTE *Bin, DWORD BinSize, char* Str, DWORD *StrSize) /CODE]

Bin: un puntero de tipo BYTE (char*) que apunta al buffer que contiene el binario a convertir a texto hexadecimal.
BinSize: El tamaño del buffer anterior.
Str: Un puntero tipo char* con un buffer que recibirá la salida del texto hexadecimal
StrSize: un puntero tipo DWORD con el tamaño del buffer Str.

Ejemplo

Supongamos que lees un binario en un puntero BYTE *Data de tamaño Size:

Código:

char *Str;  // Puntero a un buffer que recibirá la cadena
DWORD StrSize;  // tamaño del buffer

// Calculamos el tamaño de StrSize:
BinToStr(Data, Size, 0, &StrSize);
// reservamos memoria para Str
Str = new char[StrSize);
// Convertimos Data a hexadecimal
BinToStr(Data, Size, Str, &StrSize);
... No olvidar liberar el buffer Str cuando no nos haga falta (delete [] Str)

Ahora en Str tenemos una cadena ASCIIZ con un retorno de carro y línea al final y que contiene Data convertido a hexadecimal.

Saludos.


La franja horaria es GMT +2. Ahora son las 23:49:32.

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