Published by
Jan 26, 2012 (last update: Jan 26, 2012)

Hex viewer

Score: 4.1/5 (30 votes)
*****
Here is a program, in C, which will display the contents of a file in hexadecimal. Compile the code and then run it from the command-line. It takes a list of files as arguments.

Some of the code is a little ugly, namely the way I make it print colour - using #define 'd ANSI escape sequences. Not only are they ugly, but they won't work on all terminal emulators. I've checked and they work on Windows 7 (cmd.exe), Cygwin (mintty), GNOME (gnome-terminal), KDE (Konsole) and X (xterm) and they SHOULD work on whatever terminal emulator Mac OS uses, so that's like 90% of terminal emulators.

If your terminal emulator doesn't support ANSI escape sequences simply define NO_COLOR on the command-line (e.g., "gcc -DNO_COLOR -o hexview hexview.c").

If you're wondering, while (n --> 1) uses the 'hidden' "goes-to" operator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * ANSI escape sequences for colours.
 *
 * XXX	These may not work on your terminal emulator.
 * TODO	Change the method of printing colours
 *
 * If it doesn't work, try compiling with -DNO_COLOR (or /DNO_COLOR) to remove
 * the escape sequences
 */
#ifndef NO_COLOR
# define FGC_BLACK		"\033[30m"
# define FGC_DARK_RED		"\033[31m"
# define FGC_DARK_GREEN		"\033[32m"
# define FGC_DARK_YELLOW	"\033[33m"
# define FGC_DARK_BLUE		"\033[34m"
# define FGC_DARK_MAGENTA	"\033[35m"
# define FGC_DARK_CYAN		"\033[36m"
# define FGC_GRAY		"\033[37m"
# define FGC_DARK_GRAY		"\033[1;30m"
# define FGC_RED		"\033[1;31m"
# define FGC_GREEN		"\033[1;32m"
# define FGC_YELLOW		"\033[1;33m"
# define FGC_BLUE		"\033[1;34m"
# define FGC_MAGENTA		"\033[1;35m"
# define FGC_CYAN		"\033[1;36m"
# define FGC_WHITE		"\033[1;37m"
# define BGC_BLACK		"\033[40m"
# define BGC_DARK_RED		"\033[41m"
# define BGC_DARK_GREEN		"\033[42m"
# define BGC_DARK_YELLOW	"\033[43m"
# define BGC_DARK_BLUE		"\033[44m"
# define BGC_DARK_MAGENTA	"\033[45m"
# define BGC_DARK_CYAN		"\033[46m"
# define BGC_GRAY		"\033[47m"
# define BGC_DARK_GRAY		"\033[1;40m"
# define BGC_RED		"\033[1;41m"
# define BGC_GREEN		"\033[1;42m"
# define BGC_YELLOW		"\033[1;43m"
# define BGC_BLUE		"\033[1;44m"
# define BGC_MAGENTA		"\033[1;45m"
# define BGC_CYAN		"\033[1;46m"
# define BGC_WHITE		"\033[1;47m"
# define OFFSET_COLOR		BGC_DARK_RED	FGC_WHITE
# define HEX_COLOR		BGC_DARK_BLUE	FGC_WHITE
# define STRING_COLOR		BGC_DARK_GREEN	FGC_WHITE
# define NORMAL_COLOR		BGC_BLACK	FGC_WHITE
# define INFO_COLOR		BGC_BLACK	FGC_BLUE
# define ERROR_COLOR		BGC_BLACK	FGC_RED
#else
# define OFFSET_COLOR		
# define HEX_COLOR		
# define STRING_COLOR		
# define NORMAL_COLOR		
# define INFO_COLOR		
# define ERROR_COLOR		
#endif

#define BUFFERSIZE		14

typedef uint8_t byte;

/**
 * \brief	Prints the data in hexadecimal representation
 * \param p	A pointer to the string containing characters to print
 * \param n	The size of the string
 */
 */
static void printhex(const void* p, size_t n)
{
	const byte* s = (const byte*)p;
	while (n --> 1) {
		byte c = *s++;
		printf(HEX_COLOR "%02X" NORMAL_COLOR, c);
		if (n > 0)
			putchar(' ');
	}
}

/**
 * \brief	Prints the strings in a file
 * \param p	A pointer to the string containing characters to print
 * \param n	The size of the string
 */
static void printhexstr(const void* p, size_t n)
{
	const char* s = (const char*)p;
	while (n --> 1) {
		char c = *s++;
		if (!(isprint(c)))
			c = '.';
		if (c == '\n')
			c = '.';
		printf(STRING_COLOR "%c", c);
		if (n > 0)
			putchar(' ');
		printf(NORMAL_COLOR);
	}
}

/**
 * \brief	Prints the hex and strings in a file
 * \param stream A pointer to an open FILE
 * \return	On success, 0 is returned. On error, -1 is returned.
 */
static int fviewhex(FILE* stream)
{
	size_t offset = 0;
	/*
	 * Read file in small blocks
	 */
	while (!(feof(stream))) {
		static char buffer[BUFFERSIZE + 1] = {0};
		fgets(buffer, BUFFERSIZE, stream);
		/* Hex offset */
		printf(OFFSET_COLOR "%08X" NORMAL_COLOR "  ", offset);
		/* Print hex */
		printhex(buffer, BUFFERSIZE);
		printf("  ");
		/* Print strings */
		printhexstr(buffer, BUFFERSIZE);
		putchar('\n');
		offset += BUFFERSIZE;
	}
	return 0;
}

/**
 * \brief	Prints the hex and strings in a file
 * \param path	The path to the file
 * \return	On success, 0 is returned. On error, -1 is returned.
 */
static int viewhex(const char* path)
{
	FILE* stream = fopen(path, "r");
	int ret;
	if (!(stream)) {
		fprintf(stderr, ERROR_COLOR "%s: fopen %s r: %s\n", __func__, path,
							strerror(errno));
		return -1;
	}
	ret = fviewhex(stream);
	fclose(stream);
	return ret;
}

int main(int argc, char* argv[])
{
	int i;
	if (argc < 2) {
		fprintf(stderr, ERROR_COLOR "Usage: %s [file [file 2 [... [file n]]]]\n",
								argv[0]);
		exit(EXIT_FAILURE);
	}
	for (i = 1; i < argc; ++i) {
		viewhex(argv[i]);
		printf(NORMAL_COLOR "File: %s\n", argv[i]);
		
	}
	return 0;
}


Example output: http://pastebin.com/u4YGPCBi