Compilation, usage and output:
$ gcc phex.c -o phex $ ./phex phex.h 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E #include <stdio. 68 3E 0D 0A 0D 0A 76 6F 69 64 20 70 72 69 6E 74 h>____void print 46 69 6C 65 41 73 48 65 78 28 46 49 4C 45 2A 20 FileAsHex(FILE* 66 69 6C 65 29 3B 0D 0A 63 68 61 72 20 74 6F 56 file);__char toV 69 73 69 62 6C 65 43 68 61 72 61 63 74 65 72 28 isibleCharacter( 69 6E 74 20 62 79 74 65 56 61 6C 29 3B 0D 0A 76 int byteVal);__v 6F 69 64 20 77 72 69 74 65 4C 69 6E 65 28 69 6E oid writeLine(in 74 20 63 6F 75 6E 74 2C 20 63 68 61 72 2A 20 6C t count, char* l 69 6E 65 42 75 66 66 65 72 2C 20 69 6E 74 20 62 ineBuffer, int b 75 66 6C 65 6E 29 3B 0D 0A 63 68 61 72 20 75 70 uflen);__char up 70 65 72 54 6F 48 65 78 28 69 6E 74 20 62 79 74 perToHex(int byt 65 56 61 6C 29 3B 0D 0A 63 68 61 72 20 6C 6F 77 eVal);__char low 65 72 54 6F 48 65 78 28 69 6E 74 20 62 79 74 65 erToHex(int byte 56 61 6C 29 3B 0D 0A 63 68 61 72 20 6E 69 62 62 Val);__char nibb 6C 65 54 6F 48 65 78 28 69 6E 74 20 6E 69 62 62 leToHex(int nibb 6C 65 29 3B 0D 0A 0D 0A le);____
Listing: const.h
//Win32 + *nix #ifdef WIN32 #define CRLF "\r\n" #else #define CRLF "\n" #endif //number of bytes per line #define LINELEN 16
Listing: phex.h
#include <stdio.h> void printFileAsHex(FILE* file); char toVisibleCharacter(int byteVal); void writeLine(char* lineBuffer, int buflen); char upperToHex(int byteVal); char lowerToHex(int byteVal); char nibbleToHex(int nibble);
Listing: phex.c
#include "phex.h" #include "consts.h" int main(int argc, const char* argv[]) { FILE* file; if(argc != 2) { printf("Usage: phex <file>"); printf(CRLF); return 1; } file = fopen(argv[1], "rb"); if(NULL == file) { printf("Cannot open %s", argv[1]); printf(CRLF); return 2; } printFileAsHex(file); fclose(file); return 0; } void printFileAsHex(FILE* file) { int count = 0; char buffer[LINELEN]; while(1) { int byteVal = fgetc(file); if(EOF == byteVal) { break; } buffer[count] = byteVal; count++; if(count >= LINELEN) { writeLine(buffer, LINELEN); count = 0; } } if(count > 0) { writeLine(buffer, count); } } char toVisibleCharacter(int byteVal) { if(byteVal >= 32 && byteVal <= 126) { return (char) byteVal; } return '_'; } void writeLine(char* lineBuffer, int buflen) { int i; for(i=0; i<buflen; i++) { char chu = upperToHex(lineBuffer[i]); char chl = lowerToHex(lineBuffer[i]); printf("%c%c ", chu, chl); } if(buflen < LINELEN) { for(i = LINELEN - buflen; i>0; i--) { printf(" "); } } printf("\t"); for(i=0; i<buflen; i++) { char ch = toVisibleCharacter(lineBuffer[i]); printf("%c", ch); } printf(CRLF); } char upperToHex(int byteVal) { int i = (byteVal & 0xF0) >> 4; return nibbleToHex(i); } char lowerToHex(int byteVal) { int i = (byteVal & 0x0F); return nibbleToHex(i); } char nibbleToHex(int nibble) { const int ascii_zero = 48; const int ascii_a = 65; if((nibble >= 0) && (nibble <= 9)) { return (char) (nibble + ascii_zero); } if((nibble >= 10) && (nibble <= 15)) { return (char) (nibble - 10 + ascii_a); } return '?'; }
Sample Code in Subversion
A faster version with input buffering is available from source control.
Repository: http://illegalargumentexception.googlecode.com/svn/trunk/code/c/
License: MIT
Project: phex
Seen xxd? Try man xxd on Linux
ReplyDeleteThanks. xxd is orders of magnitude better than my app - I just like mucking about with code and much of what gets posted here is the random result of that.
ReplyDelete