Visualiseur hexdecimal pour console en c

Description

Ce programme permet l'affichage en mode hexadecimal du contenu binaire d'un fichier donné. Son avantage est qu'il ne lit que la partie du fichier qu'on est entrain de voir, ce qui réduit énormément les resources consommés et rend la navigation dans le contenu binaire d'un fichier rapide est aisée même s'il fait quelque centaines de MO. le tout se fait au travers des touches de navigation habituelles du clavier.
Le code utilise les fonctionnalités de conio et wincon. Il peut être vu comme un exemple d'utilisation des fonctions associées. Il peut être compilé avec mingw, cygwin ou Visual C++. Sous Cygwin, ne pas oublier d'utiliser l'option "-mno-cygwin" à gcc.

Source / Exemple :


/************************************************************************

  • *
  • A hexadecimal viewer for files on console *
  • *
  • Author : M. Idrassi *
  • *
  • History : 10-01-2004 First version *
  • *
  • *
                                                                                                                                                • /
#include <stdio.h> #include <io.h> #include <stdlib.h> #include <memory.h> #include <conio.h> #include <windows.h> #include <string.h> FILE *inputFile; long fileLength; HANDLE hStdout; CONSOLE_SCREEN_BUFFER_INFO csbiInfo; /* print a 16 byte buffer into a line */ void printBuffer(unsigned char *buffer,int counter,int blockIndex) { int i; char c; _cprintf("%.8X: ",blockIndex*16); for(i=0;i<16;i++) { if(i < counter) _cprintf("%.2X",buffer[i]); else _cprintf(" "); } _cprintf(" | "); for(i=0;i<16;i++) { if(i < counter) { c = buffer[i]; if(c == '\r' || c == '\n' || c == '\t' || c == '\b' || c == '\a' || c == '\v' || c == '\f') _cprintf("."); else _cprintf("%c",buffer[i]); } else _cprintf(" "); } } /* Given the position of the stream, print a hex preview of
  • a maximum number of bytes equal to nbLines*16
  • /
void printFile(int index,int nbLines,int nbColumns) { int i,counter; unsigned char buffer[16]; COORD cursor; cursor.X = 0; cursor.Y = 0; if(fseek(inputFile,index,SEEK_SET)) return; SetConsoleCursorPosition(hStdout,cursor); for(i=0;i<nbLines;i++) { counter = fread(buffer,1,16,inputFile); if(!counter) break; printBuffer(buffer,counter,i+(index>>4)); if(counter < 16) { i++; break; } else if(i != nbLines - 1) _cprintf("\n"); } if(counter < 16) { for(;i<nbLines;i++) { _cprintf("\n"); for(counter=0;counter<61;counter++) _cprintf(" "); } } } BOOL WINAPI ProgHandler(DWORD CtrlType) { switch(CtrlType) { case CTRL_C_EVENT: case CTRL_CLOSE_EVENT: /* free allocated resources */ fclose(inputFile); CloseHandle(hStdout); return TRUE; break; default: return FALSE; } } int main(int argc, char **argv) { int nbLines ,index,ignore,i,c,nbColumns; char str[512]; char *ptr; if(argc != 2) { printf("Usage : %s FileName\n",argv[0]); return -1; } /* open the file on binary mode for reading */ inputFile = fopen(argv[1],"rb"); if(!inputFile) { printf("Failed opening file for reading!\n"); return -1; } /* remove any path specification from the file name */ ptr = argv[1] + (strlen(argv[1]) - 1); while(ptr != argv[1] && *ptr != '\\' && *ptr != '/') ptr--; if(*ptr == '\\' || *ptr == '/') ptr++; /* get the fileLength of the file */ fileLength = filelength(fileno(inputFile)); /* put the file name and its size on the console title */ sprintf(str,"Hex Viewer by IDRASSI %s (%d bytes)",ptr,fileLength); SetConsoleTitle(str); /* We will use a new screen buffer for the viewer instead of the parent console one */ hStdout = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); SetConsoleActiveScreenBuffer(hStdout); SetConsoleCtrlHandler(ProgHandler,TRUE); index = 0; ignore = 0; while(TRUE) { if(!ignore) { /* Get the current screen buffer size and window position. */ GetConsoleScreenBufferInfo(hStdout, &csbiInfo); /* retreive the current size of the console */ nbLines = csbiInfo.srWindow.Bottom - csbiInfo.srWindow.Top + 1; nbColumns = csbiInfo.srWindow.Right - csbiInfo.srWindow.Left + 1; printFile(index,nbLines,nbColumns); } ignore = 1; /* waiting for a key stroke
  • sleep for 1ms to reduce resource consumption
  • /
while(!(i = kbhit())) Sleep(1); /* read the key */ c = getch(); if(c == 'q' || c == 'Q') break; else if(c == 0xE0) /* a function key was hit */ { c = getch(); /* get the real value */ switch(c) { case 0x4F: /* end */ case 0x75: /* CTRL + end */ { /* go to the end of the file */ index = fileLength - 16*nbLines; if(index > 0) ignore = 0; break; } case 0x77: /* CTRL + home */ case 0x47: /* home */ { /* go to the begining of the file */ index = 0; ignore = 0; break; } case 0x48: /* up */ { if(index) { index -= 16; ignore = 0; } break; } case 0x49 : /* page up */ { if(index) { /* read the previous 16*nbLines bytes on the stream */ index -= 16*nbLines; if(index < 0) index = 0; ignore = 0; } break; } case 0x50: /* down */ { if(!index || ((fileLength - index) > (nbLines*16))) { index += 16; ignore = 0; } break; } case 0x51: /* page down */ { /* read the next 16*nbLines bytes on the stream */ if(!index || ((fileLength - index) > (nbLines*16))) { index += 16*nbLines; if(index != fileLength) { ignore = 0; } } break; break; } } } } /* close the file */ fclose(inputFile); /* free the created screen buffer */ CloseHandle(hStdout); return 0; }

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.