Examinador de archivos
XM es un pequeño programa en C que hace un volcado de bytes por consola de cualquier archivo que se le pase por línea de comandos.
Muestra bloques sucesivos de 320 bytes en hexadecimal y en modo texto cuando es posible.
Permite desplazarse entre los bloques mediante las teclas de comando Arriba, Abajo, Inicio y Fin.
Se sale pulsando Escape.
Compilado con MinGW (Code::Blocks 13.12).
Descargar código fuente.
/*
xm.c
Hace un volcado de bytes por consola
del archivo que se le pasa como parámetro
en línea de comandos.
*/
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <windows.h>
#define COL 16
#define LIN 20
const int BLOQUE = LIN * COL;
typedef enum
{
eSalir = 27, /* Escape */
ePrincipio = 71, /* 'G' */
eAnterior = 72, /* 'H' */
eFinal = 79, /* 'O' */
eSiguiente = 80, /* 'P' */
eMovimiento = 224
} eComando;
typedef struct
{
unsigned long bytes; /* Tamaño del archivo en bytes */
unsigned int bloques; /* Cantidad de bloques de 320 bytes */
unsigned int resto; /* Cantidad de bytes en el último bloque */
unsigned int actual; /* Número de orden del bloque actual */
} Parte;
void gotoxy(short x, short y)
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void mostrarHexa(long pos, unsigned char *mem, unsigned int parte)
{
printf("%8lX: ", pos);
while(parte--)
{
printf(" %02X", *(mem++));
}
}
void mostrarTexto(unsigned char *mem, unsigned int parte)
{
while(parte--)
{
printf("%c", isprint(*mem)? *mem: '.');
mem++;
}
}
char leerComando()
{
unsigned char c;
gotoxy(0, 24);
printf("<Arr> Anterior | <Aba> Siguiente | <Ini> Principio | <Fin> Final | <Esc> Salir");
do
{
c = getch();
if (c == eMovimiento) c = getch();
} while(!(c == eAnterior ||
c == eSiguiente ||
c == ePrincipio ||
c == eFinal ||
c == eSalir));
return c;
}
char mostrarBloque(FILE *arch, Parte *p, const char *nomArch)
{
unsigned char mem[BLOQUE], *m;
long pos = p->actual * BLOQUE;
unsigned int parte = p->actual < p->bloques? BLOQUE: p->resto;
unsigned int lin = parte / COL, resto;
int y = 3;
system("cls");
printf("Archivo %s (%ld bytes)\nParte %d de %d",
nomArch, p->bytes, p->actual + 1, p->bloques + !!p->resto);
fseek(arch, pos, SEEK_SET);
fread(mem, parte, 1, arch);
gotoxy(0, y);
m = mem;
while(lin--)
{
mostrarHexa(pos, m, COL);
gotoxy(80 - COL, y);
mostrarTexto(m, COL);
putchar('\n');
m += COL; pos += COL;
y++;
}
resto = parte % COL;
if(resto)
{
mostrarHexa(pos, m, resto);
gotoxy(80 - COL, y);
mostrarTexto(m, resto);
}
return leerComando();
}
int main(int argc, char *argv[])
{
FILE *arch;
Parte par;
unsigned char com;
if(argc < 2)
{
puts("\nSintaxis: XM archivo\n\n");
return 1;
}
if(!(arch = fopen(argv[1], "rb")))
{
printf("\nEl archivo %s no se encuentra\n\n", argv[1]);
return 1;
}
fseek(arch, 0L, SEEK_END);
par.bytes = ftell(arch);
par.bloques = par.bytes / BLOQUE;
par.resto = par.bytes % BLOQUE;
par.actual = 0;
com = mostrarBloque(arch, &par, argv[1]);
while (com != eSalir)
{
switch(com)
{
case eSiguiente:
if(par.actual < par.bloques) par.actual++;
break;
case eAnterior:
if(par.actual) par.actual--;
break;
case eFinal:
par.actual = par.bloques - !par.resto;
break;
case ePrincipio:
par.actual = 0;
}
com = mostrarBloque(arch, &par, argv[1]);
}
fclose(arch);
return 0;
}
Muestra bloques sucesivos de 320 bytes en hexadecimal y en modo texto cuando es posible.
Permite desplazarse entre los bloques mediante las teclas de comando Arriba, Abajo, Inicio y Fin.
Se sale pulsando Escape.
Compilado con MinGW (Code::Blocks 13.12).
Descargar código fuente.
/*
xm.c
Hace un volcado de bytes por consola
del archivo que se le pasa como parámetro
en línea de comandos.
*/
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <windows.h>
#define COL 16
#define LIN 20
const int BLOQUE = LIN * COL;
typedef enum
{
eSalir = 27, /* Escape */
ePrincipio = 71, /* 'G' */
eAnterior = 72, /* 'H' */
eFinal = 79, /* 'O' */
eSiguiente = 80, /* 'P' */
eMovimiento = 224
} eComando;
typedef struct
{
unsigned long bytes; /* Tamaño del archivo en bytes */
unsigned int bloques; /* Cantidad de bloques de 320 bytes */
unsigned int resto; /* Cantidad de bytes en el último bloque */
unsigned int actual; /* Número de orden del bloque actual */
} Parte;
void gotoxy(short x, short y)
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void mostrarHexa(long pos, unsigned char *mem, unsigned int parte)
{
printf("%8lX: ", pos);
while(parte--)
{
printf(" %02X", *(mem++));
}
}
void mostrarTexto(unsigned char *mem, unsigned int parte)
{
while(parte--)
{
printf("%c", isprint(*mem)? *mem: '.');
mem++;
}
}
char leerComando()
{
unsigned char c;
gotoxy(0, 24);
printf("<Arr> Anterior | <Aba> Siguiente | <Ini> Principio | <Fin> Final | <Esc> Salir");
do
{
c = getch();
if (c == eMovimiento) c = getch();
} while(!(c == eAnterior ||
c == eSiguiente ||
c == ePrincipio ||
c == eFinal ||
c == eSalir));
return c;
}
char mostrarBloque(FILE *arch, Parte *p, const char *nomArch)
{
unsigned char mem[BLOQUE], *m;
long pos = p->actual * BLOQUE;
unsigned int parte = p->actual < p->bloques? BLOQUE: p->resto;
unsigned int lin = parte / COL, resto;
int y = 3;
system("cls");
printf("Archivo %s (%ld bytes)\nParte %d de %d",
nomArch, p->bytes, p->actual + 1, p->bloques + !!p->resto);
fseek(arch, pos, SEEK_SET);
fread(mem, parte, 1, arch);
gotoxy(0, y);
m = mem;
while(lin--)
{
mostrarHexa(pos, m, COL);
gotoxy(80 - COL, y);
mostrarTexto(m, COL);
putchar('\n');
m += COL; pos += COL;
y++;
}
resto = parte % COL;
if(resto)
{
mostrarHexa(pos, m, resto);
gotoxy(80 - COL, y);
mostrarTexto(m, resto);
}
return leerComando();
}
int main(int argc, char *argv[])
{
FILE *arch;
Parte par;
unsigned char com;
if(argc < 2)
{
puts("\nSintaxis: XM archivo\n\n");
return 1;
}
if(!(arch = fopen(argv[1], "rb")))
{
printf("\nEl archivo %s no se encuentra\n\n", argv[1]);
return 1;
}
fseek(arch, 0L, SEEK_END);
par.bytes = ftell(arch);
par.bloques = par.bytes / BLOQUE;
par.resto = par.bytes % BLOQUE;
par.actual = 0;
com = mostrarBloque(arch, &par, argv[1]);
while (com != eSalir)
{
switch(com)
{
case eSiguiente:
if(par.actual < par.bloques) par.actual++;
break;
case eAnterior:
if(par.actual) par.actual--;
break;
case eFinal:
par.actual = par.bloques - !par.resto;
break;
case ePrincipio:
par.actual = 0;
}
com = mostrarBloque(arch, &par, argv[1]);
}
fclose(arch);
return 0;
}
Comentarios
Publicar un comentario