Hex Viewer
----------------- HexView.java ----------------- import java.io.*; import java.util.*; import java.nio.*; import java.nio.charset.*; import javafx.application.*; import javafx.stage.*; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.control.cell.*; import javafx.scene.layout.*; import javafx.scene.text.*; import javafx.collections.*; import javafx.beans.property.*; import javafx.util.*; public class HexView extends Application { RandomAccessFile raf = null; int size = 0; @Override public void start(Stage stage) { File file; List<String> p = getParameters().getRaw(); if (!p.isEmpty()) { file = new File(p.get(0)); if (!file.isFile()) throw new RuntimeException(file.getName() + " file not found"); } else { file = new File("demo.bin"); if (!file.exists()) createDemo(file); } try { raf = new RandomAccessFile(file, "rw"); if (raf.length() > 0) size = (int)((raf.length() - 1) / 16 + 1); } catch (Exception e) { } iniCharTable(Charset.defaultCharset()); BorderPane layout = new BorderPane(); stage.setScene(new Scene(layout, 700, 400)); TableView<Integer> tableView = new TableView<>(); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setItems(new ObservableListBase<Integer>() { Integer value = Integer.valueOf(-1); @Override public int size() { return size; } @Override public Integer get(int index) { if (index < 0 || index >= size()) throw new IndexOutOfBoundsException(); if (index != value.intValue()) { value = Integer.valueOf(index); } return value; } }); TableColumn<Integer, String> column = new TableColumn<>(file.getName()); column.setCellValueFactory(cellData -> { return new ReadOnlyObjectWrapper<String>(createItem(cellData.getValue())); }); Font font = Font.font("Monospaced"); Callback<TableColumn<Integer, String>,TableCell<Integer, String>> columnCellFactory = column.getCellFactory(); column.setCellFactory(col -> { TableCell<Integer, String> cell = columnCellFactory.call(col); cell.setFont(font); return cell; }); tableView.getColumns().add(column); tableView.getSelectionModel().selectFirst(); tableView.sortPolicyProperty().set(t -> false); layout.setCenter(tableView); stage.setOnCloseRequest(event -> { try { raf.close(); } catch (Exception e) { } }); stage.show(); } StringBuilder sb = new StringBuilder(); char charTable[] = new char[224]; byte[] bytes = new byte[16]; char emp = '\u0020', priv = '\uE000', pnt = '\u00B7'; char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char charControl[] = { '\u0020', '\u263A', '\u263B', '\u2665', '\u2666', '\u2663', '\u2660', '\u2022', '\u25D8', '\u25CB', '\u25D9', '\u2642', '\u2640', '\u266A', '\u266B', '\u263C', '\u25BA', '\u25C4', '\u2195', '\u203C', '\u00B6', '\u00A7', '\u25AC', '\u21A8', '\u2191', '\u2193', '\u2192', '\u2190', '\u221F', '\u2194', '\u25B2', '\u25BC' }; boolean iniCharTable(Charset charset) { CharsetDecoder decoder = charset.newDecoder(); boolean sbcs = decoder.maxCharsPerByte() == 1 && decoder.averageCharsPerByte() == 1; if (!sbcs) decoder = Charset.forName("Cp1252").newDecoder(); ByteBuffer bb = ByteBuffer.allocate(1); CharBuffer cb = CharBuffer.allocate(1); for (int i = 0; i < 224; i++) { try { bb.put(0, (byte)(i + 0x20)); bb.position(0); cb.position(0); decoder.reset(); if (decoder.decode(bb, cb, true).isError()) charTable[i] = priv; else charTable[i] = cb.get(0); } catch (Exception e) { charTable[i] = priv; } } return sbcs; } String createItem(int value) { sb.setLength(0); int length = 0; try { raf.seek(value * 16); length = raf.read(bytes); } catch (Exception e) { return null; } for (int i = 28; i >= 0; i-=4) { sb.append(hexDigit[0x0F & value >>> i]); } sb.append('0').append(':').append(emp).append(emp); for (int i = 0; i < 16; i++) { if (i < length) { sb.append(hexDigit[0x0F & bytes[i] >> 4]); sb.append(hexDigit[0x0F & bytes[i]]); } else { sb.append(emp).append(emp); } sb.append(emp); if (i == 7) sb.append(emp); } sb.append(emp); for (int i = 0; i < 16; i++) { if (i >= length) { sb.append(emp); continue; } int code = 0xFF & (int)bytes[i]; if (code >= 0x00 && code < 0x20) { sb.append(charControl[code]); continue; } char uc = charTable[code - 0x20]; if (uc >= '\u0000' && uc < '\u0020') sb.append(charControl[(int)uc]); else if (uc == '\u0085' || uc == '\u2028' || uc == '\u2029') sb.append(charControl[0x0A]); else if (uc == priv) sb.append(pnt); else sb.append(uc); } return sb.toString(); } void createDemo(File file) { try (RandomAccessFile rafd = new RandomAccessFile(file, "rw")) { rafd.setLength(0L); for (int i = 0; i < 256; i++) rafd.write((byte)i); rafd.write("End".getBytes()); } catch (Exception e) { } } }