Ah, alright. Thanks.
Anyway now I am working on synchronizing the two JTextAreas. I think I have the add working correctly, but for the remove I have to override my JTextArea’s Document’s remove method. Anyway this is what I got so far (Modified from BoBear2681 's take on the code from: October 15, 2010, 01:38:18 pm)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.Position;
import javax.swing.text.Segment;
import java.util.Vector;
import java.io.*;
public class HexEditor extends JFrame{
private static final String HEXES = "0123456789ABCDEF";
JScrollPane hexScroll;
JScrollPane byteScroll;
JPanel panel;
JTextArea hexArea;
JTextArea byteArea;
JFileChooser chooser;
FileInputStream fin;
BufferedInputStream bin;
JMenuBar menuBar;
JMenu file;
JMenuItem load;
JProgressBar progressBar;
public HexEditor(){
super("Cypri's java hex editor");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
progressBar = new JProgressBar();
chooser = new JFileChooser();
load = new JMenuItem("Load");
load.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
Thread hflt = new Thread(new HexFileLoader());
hflt.start();
}
});
file = new JMenu("File");
file.add(load);
menuBar = new JMenuBar();
menuBar.add(file);
hexArea = new JTextArea(25, 16*3);
hexArea.setFont(new Font("Monospaced", Font.PLAIN, 13));
byteArea = new JTextArea(25, 16);
byteArea.setFont(new Font("Monospaced", Font.PLAIN, 13));
hexScroll = new JScrollPane(hexArea);
byteScroll = new JScrollPane(byteArea);
hexArea.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
}
@Override
public void insertUpdate(DocumentEvent e) {
try{
byteArea.insert(new String(hexStringToDisplayableByteArray(hexArea.getText(e.getOffset(), e.getLength()).replace(" ","").replace("\n", ""))), e.getOffset()/2);
System.out.println("Added: " + hexArea.getText(e.getOffset(), e.getLength()).replace(" ","").replace("\n", ""));
}
catch(Exception ex){
ex.printStackTrace();
}
}
@Override
public void removeUpdate(DocumentEvent e) {
try{
if(hexArea.getText(e.getOffset(), e.getLength()) != " ")
System.out.println("removed: " + hexArea.getText(e.getOffset(), e.getLength()));
}
catch(Exception ex){
ex.printStackTrace();
}
}
});
panel = new JPanel(new BorderLayout());
panel.add(hexScroll, BorderLayout.LINE_START);
panel.add(byteScroll, BorderLayout.LINE_END);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(BorderLayout.NORTH, menuBar);
getContentPane().add(BorderLayout.CENTER, panel);
getContentPane().add(BorderLayout.SOUTH, progressBar);
pack();
}
public static void appendHex(StringBuilder sb, int ch) {
sb.append(HEXES.charAt((ch & 0xF0) >> 4))
.append(HEXES.charAt(ch & 0x0F))
.append(' ');
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static byte[] hexStringToDisplayableByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
if (data[i / 2]<0x20 || data[i / 2]==0x7f) {
data[i / 2] = ' ';
}
}
return data;
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
HexEditor app = new HexEditor();
app.setVisible(true);
}
});
}
class HexFileLoader implements Runnable {
public void run() {
try{
chooser.showOpenDialog(HexEditor.this);
fin = new FileInputStream(chooser.getSelectedFile());
bin = new BufferedInputStream(fin);
System.out.println("File length: " + chooser.getSelectedFile().length());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setMaximum((int) chooser.getSelectedFile().length());
progressBar.setValue(0);
}
});
int ch;
System.out.println("Load start.");
long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
hexArea.setText("");
byteArea.setText("");
int numOfBytesRead = 0;
int count = 0;
while ((ch=bin.read())!=-1) {
HexEditor.appendHex(sb, ch);
if (ch<0x20 || ch==0x7f) {
ch = ' ';
}
sb2.append((char)ch);
numOfBytesRead++;
count++;
if ((count%15)==0) {
sb.append('\n');
sb2.append('\n');
}
if (count==15*36) { // 36 lines
hexArea.append(sb.toString());
byteArea.append(sb2.toString());
sb.setLength(0);
sb2.setLength(0);
count = 0;
final int b = numOfBytesRead;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue(b);
}
});
}
}
if (count>0) {
hexArea.append(sb.toString());
byteArea.append(sb2.toString());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue(progressBar.getMaximum());
}
});
}
long time = System.currentTimeMillis() - start;
System.out.println("Load completed in: " + (time/1000f) + " seconds");
} catch(Exception e) {
e.printStackTrace();
}
}
}
/*class CypriDoc implements Document{
@Override
public void addDocumentListener(DocumentListener arg0) {
// TODO Auto-generated method stub
}
@Override
public void addUndoableEditListener(UndoableEditListener arg0) {
// TODO Auto-generated method stub
}
@Override
public Position createPosition(int arg0) throws BadLocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public Element getDefaultRootElement() {
// TODO Auto-generated method stub
return null;
}
@Override
public Position getEndPosition() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLength() {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getProperty(Object arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public Element[] getRootElements() {
// TODO Auto-generated method stub
return null;
}
@Override
public Position getStartPosition() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getText(int arg0, int arg1) throws BadLocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public void getText(int arg0, int arg1, Segment arg2)
throws BadLocationException {
// TODO Auto-generated method stub
}
@Override
public void insertString(int arg0, String arg1, AttributeSet arg2)
throws BadLocationException {
// TODO Auto-generated method stub
}
@Override
public void putProperty(Object arg0, Object arg1) {
// TODO Auto-generated method stub
}
@Override
public void remove(int arg0, int arg1) throws BadLocationException {
// TODO Auto-generated method stub
}
@Override
public void removeDocumentListener(DocumentListener arg0) {
// TODO Auto-generated method stub
}
@Override
public void removeUndoableEditListener(UndoableEditListener arg0) {
// TODO Auto-generated method stub
}
@Override
public void render(Runnable arg0) {
// TODO Auto-generated method stub
}*/
}