1

I want to open a file without taking any time.When I click on open Button immediately it has been opened.But,In my application It has taken more than two minutes for large files.I try to open a file,It has size 44MB.This file takes more than two minutes time to open.I want to open large size files quickly.Once check my open action code. The below code shows the working example of my Application. Sample code:

public class OpenDemo extends javax.swing.JFrame {
JTextPane textPane;
JScrollPane scrollPane;
int i=0;
JTextField status;
public OpenDemo() {
    initComponents();
    textPane=new JTextPane();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    tp = new javax.swing.JTabbedPane();
    jMenuBar1 = new javax.swing.JMenuBar();
    jMenu1 = new javax.swing.JMenu();
    open = new javax.swing.JMenuItem();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jMenu1.setText("File");

    open.setText("Open");
    open.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            openActionPerformed(evt);
        }
    });
    jMenu1.add(open);

    jMenuBar1.add(jMenu1);

    setJMenuBar(jMenuBar1);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(tp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(tp, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
    );

    pack();
}// </editor-fold>                        

private void openActionPerformed(java.awt.event.ActionEvent evt) {                                     
    JFileChooser fileChooser=new JFileChooser();
    int result = fileChooser.showOpenDialog(this);
                    if (result==JFileChooser.APPROVE_OPTION) {
                        File file = fileChooser.getSelectedFile();
                        try {
                            textPane.setPage(file.toURI().toURL());
                        } catch(Exception e) {
                            e.printStackTrace();
                        }
                    }
      scrollPane=new JScrollPane(textPane);
      tp.add(scrollPane);
      textPane.setCaretPosition(0);   
}                                    

public static void main(String args[]) {
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new OpenDemo().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JMenu jMenu1;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JMenuItem open;
private javax.swing.JTabbedPane tp;
// End of variables declaration                   

}
Thomas W
  • 14,757
  • 6
  • 48
  • 67
  • 2
    Don't read the whole file into memory. Only read what can be shown on the screen and read the rest as needed when scrolling. – Code-Apprentice Aug 16 '14 at 04:43
  • 1
    *"I try to open a file,It has size 44MB."* Seriously? Why are you dumping 44MB on the end user? What is in this file anyway - images, a video, text..? – Andrew Thompson Aug 16 '14 at 04:44
  • 1
    "without taking any time" will not be achievable. But you can speed up things if you do not read the file line by line but in larger blocks. – Henry Aug 16 '14 at 04:47
  • 2
    Seems to me, as if the GUI hangs, when you load this huge file, that is why you were hoping to do that quickly. If that is the case consider, [SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) – nIcE cOw Aug 16 '14 at 04:49
  • 1
    See also [`JTextComponent.read(Reader,Object)`](http://docs.oracle.com/javase/8/docs/api/javax/swing/text/JTextComponent.html#read-java.io.Reader-java.lang.Object-.) – Andrew Thompson Aug 16 '14 at 04:51
  • @Andrew Thompson It's a text file,not video or images. – user3709795 Aug 16 '14 at 04:52
  • Anyone please provide solution for this problem. – user3709795 Aug 16 '14 at 04:52
  • But the user cannot realistically use '44MB' of textual data. It is far too much data to be dumping onto a simple textual component. – Andrew Thompson Aug 16 '14 at 04:53
  • @Code-Apprentice How can I achieve that solution.Please provide an example. – user3709795 Aug 16 '14 at 05:09
  • 1
    Actually, the loading of the file is not such an issue. The problem comes mainly from the JTextPane which takes forever to render huge strings. JTextArea will give you a much better result for this. – Guillaume Polet Aug 16 '14 at 10:53
  • @Guillaume Polet I have also tried with JTextArea.It is also taking time to open a large file.Please provide a better way to open. – user3709795 Aug 18 '14 at 10:40
  • @user3709795 Everything takes times. You cannot expect 44Mb of data to be displayed instantly. Now, there are some good suggestions on how you could improve: switch to a `JTable` and only parse and provide part of the text as a table model. You could probably do the same with JTextArea but haven't tried. – Guillaume Polet Aug 19 '14 at 11:57
  • I had modify my code without SwingWorker.This time I used setPage() methode of JTextPane class only.But,this time also taken more time to load file contents.Check it once... – user3709795 Aug 26 '14 at 10:43

2 Answers2

1

The SwingWorker API outlines a suitable approach. Because of the size, I'd update a TableModel, as shown here, rather than a text component. Lines will begin appearing almost immediately, while the GUI remains responsive. The listening JTable will need to render only visible lines, and you may be able to leverage sorting and filtering.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Can you provide the working example of SwingWorker or replace with my open code with SwingWorker. – user3709795 Aug 18 '14 at 06:09
  • Are these log files? Move your read loop into your worker's implementation of `doInBackground()`. Edit your question to include an [mcve](http://stackoverflow.com/help/mcve) that shows your revised approach. – trashgod Aug 18 '14 at 11:02
  • I have edit my code with mcve format.The first code is working example and my application is developed by using NetBeans IDE for Design,It generates required code.I write only the logic of openAction.And 2nd code is openAction,I want to change the OpenAction code for open large file without taking more time as mentioned above main description. – user3709795 Aug 18 '14 at 12:16
  • Where is your `SwingWorker`? – trashgod Aug 18 '14 at 16:36
  • I don't how to implement SwingWorker.Please provide solution for my Application with SwingWorker. – user3709795 Aug 20 '14 at 05:36
  • All of these [examples](http://stackoverflow.com/search?tab=votes&q=user%3a230513%20swingworker) follow the approach shown [here](http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html#publish-V...-). – trashgod Aug 20 '14 at 09:54
  • Sorry,The Swing field is new for me.I can't understand the above topic.Please include SwingWorker to my program. – user3709795 Aug 20 '14 at 10:11
  • Sadly, I am unable to adduce a complete example at this time, but I'll be happy to review your updated [mcve](http://stackoverflow.com/help/mcve). – trashgod Aug 20 '14 at 11:07
  • I edit my code with SwingWorker class.But,at this time also taking the same amount of time to load a file.Please check once and correct it.Thank you. – user3709795 Aug 22 '14 at 06:43
  • I had modify my code without SwingWorker.This time I used setPage() methode of JTextPane class only.But,this time also taken more time to load file contents.Check it once.. – user3709795 Aug 26 '14 at 10:44
  • The above provided link was also not solve the issue.Please check it alternate for my issue. – user3709795 Sep 01 '14 at 09:49
  • That's odd; even with `DefaultTableModel`, 26 MB loads promptly, and results appear immediately. – trashgod Sep 01 '14 at 18:33
  • That's enough for me.Please modify my code using DefaultTableModel. – user3709795 Sep 02 '14 at 06:18
  • What happens when you try the [complete example](http://stackoverflow.com/a/25526869/230513) on your file? – trashgod Sep 02 '14 at 12:32
1

There is some overhead (progress animation) and some things I would not have done, like a AWT event thread blocking actionPerformed.

Go with your code to https://codereview.stackexchange.com/ because a code review might be useful.

What I saw as optimizable:

Give an initial capacity to the StringBuilder.

... = new StringBuilder(1024*64); // (int)file.length()?

Replace the Scanner with a BufferdReader using readLine(). Ideal would be to check the speed of Files.readAllBytes; whether a progress indication is needed.

String s = new String(Files.readAllBytes(file.toPath()));

Second attempt:

First a sanity measure: closing the file.

Then I did less progress animation, which should definitely speed things up. It will no longer show all text in the text pane, only every hundredth line.

        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            final int PROGRESS_EVERY = 100;
            while ((line = br.readLine()) != null) {
                lineNumber++;
                text.append(line);
                text.append("\n");
                if (linenumber % PROGRESS_EVERY== 0) {
                    ProgressData data = new ProgressData();
                    data.number = lineNumber;
                    data.line = line;
                    publish(data);
                }
            }
            if (linenumber % PROGRESS_EVERY != 0) {
                ProgressData data = new ProgressData();
                data.number = lineNumber;
                data.line = line;
                publish(data);
            }
        }

And then

    private StringBuilder text = new StringBuilder(1024 * 128);

At last:

Change textPane from JTextPane to JTextArea. Considerable gain in speed.

Community
  • 1
  • 1
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • I had modify my code through above suggestions of StringBuilder with initial capacity and Replace Scanner with BufferedReader.But No difference.Please check it once. – user3709795 Aug 22 '14 at 07:27
  • The "problem" is: I have a too fast development PC. I saw you forgot an initial size for `text` but the main gain lies in reducing the progress animation. – Joop Eggen Aug 22 '14 at 08:36
  • I can't understand What was you said.If possible edit my code with your suggestions. – user3709795 Aug 22 '14 at 08:49
  • I have edited as you asked. Notice that `text` will now reserve room in advance, and the text pane will only show every hundredth line (plus the last line). – Joop Eggen Aug 22 '14 at 09:05
  • It raises the following error:incompatible types: boolean cannot be converted to int. The line as: int capacity = file.length() > Integer.MAX_VALUE : 1024 * 128 : (int) file.length(); – user3709795 Aug 22 '14 at 09:17
  • One main drawback is when checking the last line it has taken more time(nearly a minute). Every hundredth line checking was goes fast.only problem with last line checking.Check it once. – user3709795 Aug 22 '14 at 09:29
  • The first colon `:` should of course have been `?`. The time for the last line (you could remove that code) is probably a sign of something else: closing, garbage collection, a missing `SwingWorkerFrame.repaint(50L);` in actionPerformed? You might need to try without any progress code. – Joop Eggen Aug 22 '14 at 09:43
  • Without Progress code The file take nearly two minutes time to load the contents.But,using Progress code it takes nearly a minute to load contents that last line checking taken maximum time of one minute.rest of the lines loaded in within 3 seconds.Please check the last line checking code,we will succeed this application. – user3709795 Aug 22 '14 at 09:59
  • Please do something dude,You are almost done.check it once again. – user3709795 Aug 25 '14 at 08:28
  • Okay, I traced, and found that making `textPane` a `JTextArea` helps much. Added to answer. Change the code yourself, as only at two places. – Joop Eggen Aug 25 '14 at 10:06
  • Okay I know that and I tried with JTextArea.It loaded much quicker.But,In my project I wrote lot of code related to JTextPane.That's why I want to speed up file loading through JTextPane only.Provide an alternate solution related to JTextPane. – user3709795 Aug 25 '14 at 10:19
  • Sorry, I have to quit. At the end of my ideas. It is not the StringBuilder.toString, but JTextPane.setText (Document.remove+insertString does not help). Maybe setting another EditorKit, I tried `setContentType("text/plain")` but I might have done it wrong. Success. – Joop Eggen Aug 25 '14 at 10:32
  • I had modify my code without SwingWorker.This time I used setPage() methode of JTextPane class only.But,this time also taken more time to load file contents.Please Check it once.. – user3709795 Aug 26 '14 at 10:45