CyanPrime
|
 |
«
Posted
2010-10-11 05:44:05 » |
|
Alright, so I'm writing a hex editor in Java and when I load in a file around 2MB or bigger it just freezes. No errors show up though, so I'm not sure whats going on. Can anyone help me? This is the code: 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
| import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import java.util.Vector; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class HexEditor extends JFrame{ JScrollPane hexScroll; JScrollPane byteScroll; JPanel panel; JTextArea hexArea; JTextArea byteArea; JFileChooser chooser; FileInputStream fin; JMenuBar menuBar; JMenu file; JMenuItem load; public HexEditor(){ super("Cypri's java hex editor"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); chooser = new JFileChooser(); load = new JMenuItem("Load"); load.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent event) { try{ openFile(); fin = new FileInputStream(chooser.getSelectedFile()); int ch; StringBuffer strContent = new StringBuffer(""); for(int i = 0; (ch = fin.read()) != -1; i++){ String s = Integer.toHexString(ch); if(s.length() < 2) s = "0" + Integer.toHexString(ch); if(i < 10) strContent.append(" " + s.toUpperCase()); else{ strContent.append(" " + s.toUpperCase() + "\n"); i = 0; } } hexArea.setText(strContent.toString()); byte[] b = hexStringToByteArray(strContent.toString().trim()); char[] chars = new char[b.length]; String byteText = ""; int newLine = 0; for(int i = 0; i < b.length; i++){ chars[i] = (char) b[i]; byteText += chars[i]; newLine++; if(newLine > 10){ byteText += "\n"; newLine = 0; } } hexArea.setText(strContent.toString()); byteArea.setText(byteText); packMe(); } catch(Exception e){ e.printStackTrace(); } } }); file = new JMenu("File"); file.add(load); menuBar = new JMenuBar(); menuBar.add(file); hexArea = new JTextArea(); byteArea = new JTextArea(); hexScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); byteScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); panel = new JPanel(); panel.add(hexScroll); panel.add(byteScroll); hexScroll.setViewportView(hexArea); byteScroll.setViewportView(byteArea); hexArea.setPreferredSize(new Dimension(200,200)); byteArea.setPreferredSize(new Dimension(200,200)); hexScroll.setPreferredSize(new Dimension(200,200)); byteScroll.setPreferredSize(new Dimension(200,200)); getContentPane().setLayout(new BorderLayout()); getContentPane().add(BorderLayout.NORTH, menuBar); getContentPane().add(BorderLayout.CENTER, panel); pack(); setVisible(true); } public static byte[] hexStringToByteArray(String s) { int len = s.length() -1; byte[] data = new byte[(len / 2) + 1]; 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 void openFile(){ chooser.showOpenDialog(null); } public void packMe(){ pack(); } public static void main(String[] args){ HexEditor app = new HexEditor(); } } |
|
|
|
|
Eli Delventhal
|
 |
«
Reply #1 - Posted
2010-10-11 05:53:40 » |
|
Probably just gets grogged down creating and concatenating Strings. You're using a StringBuffer in there, which is good, but you shouldn't be creating any strings at all if possible (i.e. two append() calls are better than myStr = "0" + xxxx).
Also, run in debug and pause execution when it appears frozen. See what it's doing. Also try printing out every 100th line or something so you can narrow down where it's breaking.
|
|
|
|
dime
Senior Newbie 
|
 |
«
Reply #2 - Posted
2010-10-11 07:01:39 » |
|
I don't use AWT, but looks like your loading the data in the main GUI thread. This generally is very bad in most GUIs.
In SWT I would throw the load function to a new thread and async output to a progress window/bar.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
gouessej
|
 |
«
Reply #3 - Posted
2010-10-11 08:19:31 » |
|
dime is right, perform your heavy operations on another thread. Why not using a SwingWorker?
|
|
|
|
erikd
|
 |
«
Reply #4 - Posted
2010-10-11 08:24:00 » |
|
dime is right, perform your heavy operations on another thread. Why not using a SwingWorker? Perhaps because it's just a quick & dirty hexeditor and he couldn't be bothered with that stuff  This is not really the problem here. You get an OutOfMemoryError. Just give it more memory, or make it more memory efficient.
|
|
|
|
CyanPrime
|
 |
«
Reply #5 - Posted
2010-10-11 18:41:00 » |
|
Okay, I've changed my code but I'm still stuck in the loop, and it won't repaint/revalidate despite me telling it to in the loop. New code: 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
| import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
import javax.swing.*; import java.util.Vector; import java.io.File; import java.io.FileInputStream; import java.io.InputStream;
public class HexEditor extends JFrame{ JScrollPane hexScroll; JScrollPane byteScroll; JPanel panel; JTextArea hexArea; JTextArea byteArea; JFileChooser chooser; FileInputStream fin; JMenuBar menuBar; JMenu file; JMenuItem load;
public HexEditor(){ super("Cypri's java hex editor"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); chooser = new JFileChooser(); load = new JMenuItem("Load"); load.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent event) { try{ openFile(); fin = new FileInputStream(chooser.getSelectedFile()); int ch; StringBuffer strContent = new StringBuffer(""); System.out.println("Load start."); hexArea.setText(""); while((ch = fin.read()) != -1){ System.out.println("Loop start."); if(Integer.toHexString(ch).length() < 2){ hexArea.append(" 0" + Integer.toHexString(ch).toUpperCase()); } else{ hexArea.append(" " + Integer.toHexString(ch).toUpperCase()); } hexArea.revalidate(); hexScroll.revalidate(); panel.revalidate(); revalidateMe(); System.out.println("Loop end."); }
System.out.println("Out of loop."); byteArea.setText(""); byteArea.append(hexStringToByteArray(strContent.toString().trim()).toString()); packMe(); } catch(Exception e){ e.printStackTrace(); } } }); file = new JMenu("File"); file.add(load); menuBar = new JMenuBar();
menuBar.add(file); hexArea = new JTextArea(); byteArea = new JTextArea(); hexArea.setLineWrap(true); byteArea.setLineWrap(true); hexScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); byteScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); panel = new JPanel(); panel.add(hexScroll); panel.add(byteScroll); hexScroll.setViewportView(hexArea); byteScroll.setViewportView(byteArea); hexScroll.setPreferredSize(new Dimension(440,480)); byteScroll.setPreferredSize(new Dimension(200,480));
getContentPane().setLayout(new BorderLayout()); getContentPane().add(BorderLayout.NORTH, menuBar); getContentPane().add(BorderLayout.CENTER, panel); pack(); setVisible(true); } public static byte[] hexStringToByteArray(String s) { int len = s.length() -1; byte[] data = new byte[(len / 2) + 1]; 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 void openFile(){ chooser.showOpenDialog(null); } public void packMe(){ pack(); } public void revalidateMe(){ repaint(); } public static void main(String[] args){ HexEditor app = new HexEditor(); } } |
|
|
|
|
CyanPrime
|
 |
«
Reply #6 - Posted
2010-10-11 18:52:18 » |
|
Letting it run for a while in the loop gave me this error: 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
| Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space at javax.swing.text.GapContent.allocateArray(Unknown Source) at javax.swing.text.GapVector.resize(Unknown Source) at javax.swing.text.GapVector.shiftEnd(Unknown Source) at javax.swing.text.GapContent.shiftEnd(Unknown Source) at javax.swing.text.GapVector.open(Unknown Source) at javax.swing.text.GapVector.replace(Unknown Source) at javax.swing.text.GapContent.insertString(Unknown Source) at javax.swing.text.AbstractDocument.handleInsertString(Unknown Source) at javax.swing.text.AbstractDocument.insertString(Unknown Source) at javax.swing.text.PlainDocument.insertString(Unknown Source) at javax.swing.JTextArea.append(Unknown Source) at HexEditor$1.actionPerformed(HexEditor.java:47) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.AbstractButton.doClick(Unknown Source) at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source) at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space at javax.swing.text.GapContent.getChars(Unknown Source) at javax.swing.text.AbstractDocument.getText(Unknown Source) at javax.swing.text.WrappedPlainView.loadText(Unknown Source) at javax.swing.text.WrappedPlainView.calculateBreakPosition(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.breakLines(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.getLineEnds(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.paint(Unknown Source) at javax.swing.text.BoxView.paintChild(Unknown Source) at javax.swing.text.BoxView.paint(Unknown Source) at javax.swing.text.WrappedPlainView.paint(Unknown Source) at javax.swing.plaf.basic.BasicTextUI$RootView.paint(Unknown Source) at javax.swing.plaf.basic.BasicTextUI.paintSafely(Unknown Source) at javax.swing.plaf.basic.BasicTextUI.paint(Unknown Source) at javax.swing.plaf.basic.BasicTextUI.update(Unknown Source) at javax.swing.JComponent.paintComponent(Unknown Source) at javax.swing.JComponent.paint(Unknown Source) at javax.swing.JComponent.paintChildren(Unknown Source) at javax.swing.JComponent.paint(Unknown Source) at javax.swing.JViewport.paint(Unknown Source) at javax.swing.JComponent.paintChildren(Unknown Source) at javax.swing.JComponent.paint(Unknown Source) at javax.swing.JComponent.paintToOffscreen(Unknown Source) at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) at javax.swing.RepaintManager.paint(Unknown Source) at javax.swing.JComponent._paintImmediately(Unknown Source) at javax.swing.JComponent.paintImmediately(Unknown Source) at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source) at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source) at java.awt.event.InvocationEvent.dispatch(Unknown Source) Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space at javax.swing.text.GapContent.getChars(Unknown Source) at javax.swing.text.AbstractDocument.getText(Unknown Source) at javax.swing.text.WrappedPlainView.loadText(Unknown Source) at javax.swing.text.WrappedPlainView.calculateBreakPosition(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.breakLines(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.getLineEnds(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.modelToView(Unknown Source) at javax.swing.text.CompositeView.modelToView(Unknown Source) at javax.swing.text.BoxView.modelToView(Unknown Source) at javax.swing.plaf.basic.BasicTextUI$RootView.modelToView(Unknown Source) at javax.swing.plaf.basic.BasicTextUI.modelToView(Unknown Source) at javax.swing.text.DefaultCaret.repaintNewCaret(Unknown Source) at javax.swing.text.DefaultCaret$1.run(Unknown Source) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space at javax.swing.text.GapContent.getChars(Unknown Source) at javax.swing.text.AbstractDocument.getText(Unknown Source) at javax.swing.text.WrappedPlainView.loadText(Unknown Source) at javax.swing.text.WrappedPlainView.calculateBreakPosition(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.breakLines(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.getLineEnds(Unknown Source) at javax.swing.text.WrappedPlainView$WrappedLine.modelToView(Unknown Source) at javax.swing.text.CompositeView.modelToView(Unknown Source) at javax.swing.text.BoxView.modelToView(Unknown Source) at javax.swing.plaf.basic.BasicTextUI$RootView.modelToView(Unknown Source) at javax.swing.plaf.basic.BasicTextUI.modelToView(Unknown Source) at javax.swing.text.DefaultCaret.repaintNewCaret(Unknown Source) at javax.swing.text.DefaultCaret$1.run(Unknown Source) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space |
|
|
|
|
Eli Delventhal
|
 |
«
Reply #7 - Posted
2010-10-11 19:31:22 » |
|
As erikd just said, your heap is too low. Increase the min/max heap size and try again. Or try to be more efficient about how much is in memory at once time.
|
|
|
|
CyanPrime
|
 |
«
Reply #8 - Posted
2010-10-11 23:49:50 » |
|
Okay, so Java seems to be way too slow to do this. I've gotten it to work more or less, but it's still way too slow. I'm thinking about trying this in C# and .net.
|
|
|
|
BoBear2681
|
 |
«
Reply #9 - Posted
2010-10-12 01:56:22 » |
|
As far as the performance and responsiveness, you shouldn't load the content into the text area on the EDT. Either launch a separate Thread to read from the file or use a SwingWorker. Doing file IO on the EDT as you're doing now will obviously cause freezes in the GUI. Using a separate thread should improve the user experience 100%.
Prior to Java 7, JTextArea.append() was labeled as threadsafe in its Javadoc, but as of Java 7 they've taken that statement away, so that's something to keep in mind - might want to ensure that's called on the EDT.
It's probably also not a bad idea to wrap your FileInputStream in a BufferedInputStream, the benefits will be more noticeable the bigger your file is.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
CyanPrime
|
 |
«
Reply #10 - Posted
2010-10-12 16:47:33 » |
|
Alright the thread thing worked. It loads rather fast now. I'm impressed.
|
|
|
|
erikd
|
 |
«
Reply #11 - Posted
2010-10-12 17:16:15 » |
|
That's good because just switching platforms because you have a performance bug would have been a rather shortsighted thing to do 
|
|
|
|
CyanPrime
|
 |
«
Reply #12 - Posted
2010-10-12 17:16:51 » |
|
This is the output of a normal hex editor's btyes section. ...Okay, I guess I can't copy it? anyway there's a line in files byte code that says "This program can't be ran in dos mode" this is that line in my hex editor: Edit: okay, when I click the byte area it freezes so I can't copy that eather, but it's something like "d[]S m[][]d" Anyway you guys got any idea why it's freezing? Here is the code: 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
| import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
import javax.swing.*; import java.util.Vector; import java.io.File; import java.io.FileInputStream; import java.io.InputStream;
public class HexEditor extends JFrame{ JScrollPane hexScroll; JScrollPane byteScroll; JPanel panel; JTextArea hexArea; JTextArea byteArea; JFileChooser chooser; FileInputStream fin; JMenuBar menuBar; JMenu file; JMenuItem load;
public HexEditor(){ super("Cypri's java hex editor"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); chooser = new JFileChooser(); load = new JMenuItem("Load"); load.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent event) { Thread hflt = new Thread(new HexFileLoader(passMe())); hflt.start(); } }); file = new JMenu("File"); file.add(load); menuBar = new JMenuBar();
menuBar.add(file); hexArea = new JTextArea(); byteArea = new JTextArea(); hexArea.setLineWrap(true); hexArea.setWrapStyleWord(true); byteArea.setLineWrap(true); hexScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); byteScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); panel = new JPanel(); panel.add(hexScroll); panel.add(byteScroll); hexScroll.setViewportView(hexArea); byteScroll.setViewportView(byteArea); hexScroll.setPreferredSize(new Dimension(440,480)); byteScroll.setPreferredSize(new Dimension(200,480));
getContentPane().setLayout(new BorderLayout()); getContentPane().add(BorderLayout.NORTH, menuBar); getContentPane().add(BorderLayout.CENTER, panel); pack(); setVisible(true); } public static byte[] hexStringToByteArray(String s) { int len = s.length() -1; byte[] data = new byte[(len / 2) + 1]; 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 char[] hexStringToByteCharArray(String s) { int len = s.length() -1; byte[] data = new byte[(len / 2) + 1]; char[] chardata = new char[(len / 2) + 1]; 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)); chardata[i / 2] = (char) data[i / 2]; } return chardata; }
public void openFile(){ chooser.showOpenDialog(null); } public void packMe(){ pack(); } public void revalidateMe(){ repaint(); } public HexEditor passMe(){ return this; } public static void main(String[] args){ HexEditor app = new HexEditor(); } }
class HexFileLoader implements Runnable { HexEditor parent; HexFileLoader(HexEditor parent) { this.parent = parent; }
public void run() { try{ parent.openFile(); parent.fin = new FileInputStream(parent.chooser.getSelectedFile()); int ch; System.out.println("Load start."); parent.hexArea.setText(""); parent.byteArea.setText(""); while((ch = parent.fin.read()) != -1){ if(Integer.toHexString(ch).length() < 2){ parent.hexArea.append(" 0" + Integer.toHexString(ch).toUpperCase()); } else{ parent.hexArea.append(" " + Integer.toHexString(ch).toUpperCase()); } parent.byteArea.setText(String.valueOf(HexEditor.hexStringToByteCharArray(parent.hexArea.getText().trim()))); }
System.out.println("Out of loop."); parent.packMe(); } catch(Exception e){ e.printStackTrace(); } } } |
|
|
|
|
CyanPrime
|
 |
«
Reply #13 - Posted
2010-10-12 17:27:47 » |
|
That's good because just switching platforms because you have a performance bug would have been a rather shortsighted thing to do  Yeah, I guess so. 
|
|
|
|
Riven
|
 |
«
Reply #14 - Posted
2010-10-12 18:01:35 » |
|
I merged your new thread back into this one.
Anyway, to answer your question:
Do not put binary into a JTextArea (your byteArea). It just just a bad idea, it doesn't work for you, and even if it works it's useless, because there are a lot of non-printable characters. You might want to 'escape' the non-printable chars, like converting 0x03 to '\x03'.
I do understand you want to display HEX, but why do you want to see binary in a JTextArea?
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings!
|
|
|
BoBear2681
|
 |
«
Reply #15 - Posted
2010-10-12 18:09:49 » |
|
In your loop, it looks like you can replace this: 1
| parent.byteArea.setText(String.valueOf(HexEditor.hexStringToByteCharArray(parent.hexArea.getText().trim()))); |
with this: 1
| parent.byteArea.append((char)ch); |
My only guess about your inability to select the text in your ascii view is that JTextArea isn't liking unprintable characters in its text. You could try using filtering them out: 1 2 3 4
| if (ch<0x20 || ch==0x7f) { ch = ' '; } parent.byteArea.append((char)ch); |
|
|
|
|
CyanPrime
|
 |
«
Reply #16 - Posted
2010-10-12 20:44:12 » |
|
That seemed to work for both problems. Thank you. ^_^
|
|
|
|
CyanPrime
|
 |
«
Reply #17 - Posted
2010-10-12 21:15:25 » |
|
Okay, file-loading is responsive, but it's still very slow. How would a BufferedInputStream help me exactly?
|
|
|
|
Riven
|
 |
«
Reply #18 - Posted
2010-10-12 21:23:08 » |
|
Okay, file-loading is responsive, but it's still very slow. How would a BufferedInputStream help me exactly?
The javadoc explains it pretty well
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings!
|
|
|
CyanPrime
|
 |
«
Reply #19 - Posted
2010-10-12 22:10:15 » |
|
The javadoc explains it pretty well
A BufferedInputStream adds functionality to another input stream-namely, the ability to buffer the input and to support the mark and reset methods. When the BufferedInputStream is created, an internal buffer array is created. As bytes from the stream are read or skipped, the internal buffer is refilled as necessary from the contained input stream, many bytes at a time. The mark operation remembers a point in the input stream and the reset operation causes all the bytes read since the most recent mark operation to be reread before new bytes are taken from the contained input stream. --- So...it reads into a buffer? This sounds like it'll take longer to read the file.
|
|
|
|
BoBear2681
|
 |
«
Reply #20 - Posted
2010-10-12 23:01:19 » |
|
It does bulk reads from the underlying input stream, and is thus faster in cases where reading from that stream is costly. In your case, it's faster to read chunks of bytes at a time from a file as opposed to a single byte at a time, as there is less disk IO.
|
|
|
|
CyanPrime
|
 |
«
Reply #21 - Posted
2010-10-12 23:09:06 » |
|
It does bulk reads from the underlying input stream, and is thus faster in cases where reading from that stream is costly. In your case, it's faster to read chunks of bytes at a time from a file as opposed to a single byte at a time, as there is less disk IO.
Seems the same to me. Do I need to use something other than read()?
|
|
|
|
Riven
|
 |
«
Reply #22 - Posted
2010-10-12 23:11:59 » |
|
Seems the same to me. Do I need to use something other than read()?
Are you really going to keep posting about how unlikely you think the solution is?
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings!
|
|
|
CyanPrime
|
 |
«
Reply #23 - Posted
2010-10-12 23:14:39 » |
|
Are you really going to keep posting about how unlikely you think the solution is?
What do you mean?
|
|
|
|
CyanPrime
|
 |
«
Reply #24 - Posted
2010-10-12 23:25:17 » |
|
Hmm, am I doing the buffered read wrong? cause it's no faster than a byte by byte read for me even though I'm reading 1000 bytes at a time. this is my code: 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 169 170 171 172 173 174 175 176
| import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
import javax.swing.*; import java.util.Vector; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream;
public class HexEditor extends JFrame{ 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(passMe())); hflt.start(); } }); file = new JMenu("File"); file.add(load); menuBar = new JMenuBar();
menuBar.add(file); hexArea = new JTextArea(); byteArea = new JTextArea(); hexArea.setLineWrap(true); hexArea.setWrapStyleWord(true); byteArea.setLineWrap(true); hexScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); byteScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); panel = new JPanel(); panel.add(hexScroll); panel.add(byteScroll); hexScroll.setViewportView(hexArea); byteScroll.setViewportView(byteArea); hexScroll.setPreferredSize(new Dimension(440,480)); byteScroll.setPreferredSize(new Dimension(200,480));
getContentPane().setLayout(new BorderLayout()); getContentPane().add(BorderLayout.NORTH, menuBar); getContentPane().add(BorderLayout.CENTER, panel); getContentPane().add(BorderLayout.SOUTH, progressBar); pack(); setVisible(true); } public static byte[] hexStringToByteArray(String s) { int len = s.length() -1; byte[] data = new byte[(len / 2) + 1]; 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 char[] hexStringToByteCharArray(String s) { int len = s.length() -1; byte[] data = new byte[(len / 2) + 1]; char[] chardata = new char[(len / 2) + 1]; 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)); chardata[i / 2] = (char) data[i / 2]; } return chardata; }
public void openFile(){ chooser.showOpenDialog(null); } public void packMe(){ pack(); } public void revalidateMe(){ repaint(); } public HexEditor passMe(){ return this; } public static void main(String[] args){ HexEditor app = new HexEditor(); } }
class HexFileLoader implements Runnable { HexEditor parent; HexFileLoader(HexEditor parent) { this.parent = parent; }
public void run() { try{ parent.openFile(); parent.fin = new FileInputStream(parent.chooser.getSelectedFile()); parent.bin = new BufferedInputStream(parent.fin); System.out.println("(int) parent.chooser.getSelectedFile().getTotalSpace(): " + (int) parent.chooser.getSelectedFile().length()); parent.progressBar.setMaximum((int) parent.chooser.getSelectedFile().length()); parent.progressBar.setValue(0); int ch; System.out.println("Load start."); parent.hexArea.setText(""); parent.byteArea.setText(""); int numOfBytesRead = 0; byte[] buf = new byte[1000]; while((ch = parent.bin.read(buf)) != -1){ for(int i = 0; i < 1000; i++){ if(Integer.toHexString(buf[i]).length() < 2){ parent.hexArea.append(" 0" + Integer.toHexString(buf[i]).toUpperCase()); } else{ parent.hexArea.append(" " + Integer.toHexString(buf[i]).toUpperCase()); } if (ch<0x20 || ch==0x7f) { ch = ' '; } parent.byteArea.append(String.valueOf((char)buf[i])); numOfBytesRead++; parent.progressBar.setValue(numOfBytesRead); } }
System.out.println("Out of loop."); parent.packMe(); } catch(Exception e){ e.printStackTrace(); } } } |
|
|
|
|
Riven
|
 |
«
Reply #25 - Posted
2010-10-12 23:38:04 » |
|
That's because you have a bunch of bottlenecks, and you just solved one (introducing a brand new bug: always reading multiples of 1000 bytes, even if there are not that many bytes)
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings!
|
|
|
CyanPrime
|
 |
«
Reply #26 - Posted
2010-10-12 23:40:07 » |
|
That's because you have a bunch of bottlenecks, and you just solved one (introducing a brand new bug: always reading multiples of 1000 bytes, even if there are not that many bytes)
Yeah, I figured I had that bug, but I'm more worried about the speed right now. What are some ways I can speed up my code?
|
|
|
|
CyanPrime
|
 |
«
Reply #27 - Posted
2010-10-13 06:36:52 » |
|
Alright, it's kinda fast now. anyone have any other ideas I can use? See any bugs? 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
| import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
import javax.swing.*; import java.util.Vector; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream;
public class HexEditor extends JFrame{ 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(passMe())); hflt.start(); } }); file = new JMenu("File"); file.add(load); menuBar = new JMenuBar();
menuBar.add(file); hexArea = new JTextArea(); byteArea = new JTextArea(); hexArea.setLineWrap(true); hexArea.setWrapStyleWord(true); byteArea.setLineWrap(true); hexScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); byteScroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); panel = new JPanel(); panel.add(hexScroll); panel.add(byteScroll); hexScroll.setViewportView(hexArea); byteScroll.setViewportView(byteArea); hexScroll.setPreferredSize(new Dimension(440,480)); byteScroll.setPreferredSize(new Dimension(200,480));
getContentPane().setLayout(new BorderLayout()); getContentPane().add(BorderLayout.NORTH, menuBar); getContentPane().add(BorderLayout.CENTER, panel); getContentPane().add(BorderLayout.SOUTH, progressBar); pack(); setVisible(true); } public void openFile(){ chooser.showOpenDialog(null); } public void packMe(){ pack(); } public void revalidateMe(){ repaint(); } public HexEditor passMe(){ return this; } public static String getHex( byte [] raw ) { if ( raw == null ) { return null; } final StringBuilder hex = new StringBuilder( 2 * raw.length ); for ( final byte b : raw ) { hex.append(HEXES.charAt((b & 0xF0) >> 4)) .append(HEXES.charAt((b & 0x0F))) .append(" "); } return hex.toString(); }
public static void main(String[] args){ HexEditor app = new HexEditor(); } }
class HexFileLoader implements Runnable { HexEditor parent; HexFileLoader(HexEditor parent) { this.parent = parent; }
public void run() { try{ parent.openFile(); parent.fin = new FileInputStream(parent.chooser.getSelectedFile()); parent.bin = new BufferedInputStream(parent.fin); System.out.println("(int) parent.chooser.getSelectedFile().getTotalSpace(): " + (int) parent.chooser.getSelectedFile().length()); parent.progressBar.setMaximum((int) parent.chooser.getSelectedFile().length()); parent.progressBar.setValue(0); int ch; System.out.println("Load start."); parent.hexArea.setText(""); parent.byteArea.setText(""); int numOfBytesRead = 0; byte[] buf; if((int) parent.chooser.getSelectedFile().length() > 10000) buf = new byte[10000]; else buf = new byte[(int) parent.chooser.getSelectedFile().length()]; while((ch = parent.bin.read(buf)) != -1){ parent.hexArea.append(HexEditor.getHex(buf)); parent.byteArea.append(new String(buf)); numOfBytesRead += buf.length; parent.progressBar.setValue(numOfBytesRead); }
System.out.println("Out of loop."); parent.packMe(); } catch(Exception e){ e.printStackTrace(); } } } |
|
|
|
|
Eli Delventhal
|
 |
«
Reply #28 - Posted
2010-10-14 03:27:50 » |
|
If you're ever trying to improve speed, the first thing to do is find where the bottleneck is. To do that, you can either use System.nanoTime() and print out time requirements in the code, or you can use a profiler like Shark.
Either way, looking at your code won't help too much now. Instead, figure out what's taking up all the time and cut it out.
|
|
|
|
Riven
|
 |
«
Reply #29 - Posted
2010-10-14 08:02:34 » |
|
Well, the bottleneck is right here: 1 2 3 4
| parent.hexArea.append(HexEditor.getHex(buf)); parent.byteArea.append(new String(buf)); numOfBytesRead += buf.length; parent.progressBar.setValue(numOfBytesRead); |
3 UI updates for every byte...
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings!
|
|
|
|