Search code examples
javaswingfile-iobufferedreaderjprogressbar

How do I track reading of a a file using .readLine() in java?


I am reading a file using bufferedREader ,the file is a text file with lot of text

here is how I am reading it

 while(true)  //I know the loop is not perfect just ignore it for now, i wanna concentrate on the tracking
                {
                      try
                      {
                       br.readLine();
                      }
                      catch(IOException e)
                      {
                      break;
                      }
                      catch (Exception e)
                      {
                      break;
                      }
                }

I want to track what percentage of the file I have read so I can use that percentage value in my progress bar like this:

while(true)
                {
                      try
                      {
                       br.readLine();
                       progressBar.setValue(percentageRead);//how do I get percentageRead value dynamically?
                      }
                      catch(IOException e)
                      {
                      break;
                      }
                      catch (Exception e)
                      {
                      break;
                      }
                }

Solution

  • There are any number ways to achieve this, but you need to keep four things in mind...

    1. You need to know how much you are reading
    2. You need to know how much you have read
    3. You should never performing any action within context of the Event Dispatching Thread that might block it (such as long running loops or blocking I/O)
    4. You should never modify or change the state of the UI from any thread other then the Event Dispatching Thread

    This example simply uses a SwingWorker to read the file in a background thread and uses it's progress functionality to post updates back to the context of the EDT.

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.GridBagLayout;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutionException;
    import javax.swing.JFrame;
    import javax.swing.JProgressBar;
    import javax.swing.SwingWorker;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class ReadFile {
    
        public static void main(String[] args) {
            new ReadFile();
        }
    
        public ReadFile() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    final JProgressBar pb = new JProgressBar(0, 100);
                    final ReadFileWorker worker = new ReadFileWorker();
                    worker.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
                                pb.setValue(worker.getProgress());
                            }
                        }
                    });
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new GridBagLayout());
                    frame.add(pb);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    worker.execute();
                }
            });
        }
    
        public class ReadFileWorker extends SwingWorker<List<String>, String> {
    
            @Override
            protected List<String> doInBackground() throws Exception {
                List<String> lines = new ArrayList<>(25);
                File textFile = new File("Test.txt");
                long byteLength = textFile.length();
    
                System.out.println("Reading " + byteLength + " bytes...");
    
                try (InputStream is = new FileInputStream(textFile)) {
    
                    byte[] content = new byte[1024];
                    int bytesRead = -1;
                    long totalBytes = 0;
                    String lastText = "";
                    while ((bytesRead = is.read(content)) != -1) {
    
                        totalBytes += bytesRead;
                        setProgress(Math.round(((float) totalBytes / (float) byteLength) * 100f));
    
                        String text = lastText + new String(content);
                        boolean keepEnd = !text.endsWith("\n");
                        String[] parts = text.split("\n");
    
                        for (int count = 0; count < (keepEnd ? parts.length - 1 : parts.length); count++) {
                            lines.add(parts[count]);
                            publish(parts[count]);
                        }
    
                        if (keepEnd) {
                            lastText = parts[parts.length - 1];
                        } else {
                            lastText = "";
                        }
    
                        // This is only here to slow the demonstration down
                        Thread.sleep(5);
    
                    }
    
                    System.out.println("Read " + totalBytes + " bytes...");
                    System.out.println("Read " + lines.size() + " lines...");
    
                } finally {
    
                }
    
                return lines;
            }
    
            @Override
            protected void done() {
                try {
                    List<String> lines = get();
                } catch (InterruptedException | ExecutionException ex) {
                    ex.printStackTrace();
                }
            }
    
        }
    
    }
    

    Now, you could incorporate the SwingWorker with one of the other "ProgressInputStream" implementations as well. Take a look at Concurrency in Swing for more details