After I received comments from ispak on Flickr I made a few fixes.
ispak pointed out that it was a bad idea reading one byte at the time, also I had a gay ass try/catch that didn’t catch any exception :p
So now I read 16 byte chunks, and I also take care of the file ending. The previous version used to print the file ending with a bunch of null bytes. Now it stops reading at the end, and formats the output accordingly.
Here’s the new source:
[java]
//HexViewer.java
import java.io.*;
public final class HexViewer {
public final static void printFile(String filePath) {
try {
File f = new File(filePath);
BufferedInputStream bis =
new BufferedInputStream(new FileInputStream(f));
byte[] chunk = null;
int readStatus = 0;
while (true) {
chunk = new byte[16];
readStatus = bis.read(chunk, 0, 16);
char[] line = new char[16];
if (readStatus == -1)
break;
for (byte i=0; i < readStatus; i++) {
int readByte = (chunk[i] < 0) ? (-1 * (int) chunk[i]) : chunk[i];
String paddingZero = (readByte < 16) ? "0" : "";
System.out.print(paddingZero + Integer.toHexString(readByte).toUpperCase() + " ");
line[i] = (readByte >= 33 && readByte <= 126) ? (char) readByte : ‘.’;
}
//We add some padding to print the text line right below the one above.
String padding = new String();
if (readStatus < 16) {
for (byte i=0; i < 16-readStatus; i++) {
padding += " ";
}
}
System.out.println(padding + new String(line));
}
} catch (Exception e1) { e1.printStackTrace(); }
}
public final static void main(String[] args) {
if (args.length == 0)
return;
printFile(args[0]);
}
}
[/java]
And see how it now handles file endings when the file size is not a multiple of 16 :p
the byte to int conversion should be
int readByte = chunk[i] & 0x000000ff
otherwise you would run into problems with unicode, but on the other hand i used byte data converted from Java strings rather than direct file input.