0

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;
                      }
                }
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Snedden27
  • 1,870
  • 7
  • 32
  • 60

4 Answers4

3

Use a FileInputStream, javax.swing.ProgressMonitorInputStream, InputStreamReader, and a BufferedReader. Then it all happens automatically.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • the problem with that is that it opens its own progress bar ,I want to add the value to the progress bar I have instatiated – Snedden27 Nov 07 '13 at 02:02
  • @Snedden27 Don't bother. Use what's built in. – user207421 Nov 07 '13 at 02:03
  • Then you'll have to either count the number of lines ahead of time or report progress in terms of bytes. – user207421 Nov 07 '13 at 02:10
  • The code behind the ProgressMonitorInputStream can't be that complicated.... it's just a filter on the input stream..... – rolfl Nov 07 '13 at 02:11
  • hmm for now I just read the number of line and divide the current line by the total, got due in 3 hours, may be would explore that later, thanks for your comments tho – Snedden27 Nov 07 '13 at 02:20
2

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

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Easy

private class myProgressBar{
     private int read;

     //override constructor and such... 

     @Override 
     public int read(byte[] data, int offset, int length) throws IOException
      {
        int t = super.read(data, offset, length);
        if ( t > 0 )
        {
         read += t;
        }
        return t;
       }

  }

then just use standard getter methods. You can get maximum by using myInputStream.availble();

link to relevant source code: http://developer.classpath.org/doc/javax/swing/ProgressMonitorInputStream-source.html

Skylion
  • 2,696
  • 26
  • 50
  • I don't believe `availble` is a reliable measure for the total content that might come through the input stream – MadProgrammer Nov 07 '13 at 02:22
  • That is what the class ProgressMonitorInputStream uses though. – Skylion Nov 07 '13 at 02:22
  • From the JavaDocs *"Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream"* - File streams might be different, I'm just saying ;) – MadProgrammer Nov 07 '13 at 02:33
  • Feel free to call Oracle and ask them to change their JDK. :) Or contribute to OpenJDK – Skylion Nov 07 '13 at 02:38
  • No worries, in the mean time, feel free to provide a workable solution ;) – MadProgrammer Nov 07 '13 at 02:40
0

As a quick 'hack' you can implement a counting FilterInputStream, and use it in a way that EJP suggests:

public class ProgressInputStream extends FilterInputStream {

    private final double maxbytes;
    private long current = 0;

    public ProgressInputStream(InputStream in, long bytestoexpect) {
        super(in);
        maxbytes = (double)bytestoexpect;
    }

    /**
     * return a value between 0.0 and 1.0 to represent the progress.
     * should do some division-by-zero checking here too.
     */
    public double getProgress() {
        return current / maxbytes;
    }

    @Override
    public int read() throws IOException {
        final int ret = super.read();
        if (ret >= 0) {
            current++;
        }
        return ret;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        final int ret = super.read(b, off, len);
        current += ret;
        return ret;
    }

    @Override
    public int read(byte[] b) throws IOException {
        // TODO Auto-generated method stub
        final int ret = super.read(b);
        current += ret;
        return ret;
    }

    @Override
    public long skip(long n) throws IOException {
        final long ret = super.skip(n);
        current += ret;
        return ret;
    }

}

Then, your code can do:

final File infile = new File("path/to/file");
final long insize = infile.length();
final ProgresInputStream pis = new ProgressInputStream(new FileInputStream(infile), insize);
BufferedReader br = new BufferedReader(new InputStreamReader(pis));
String line = null;
try {
    while((line = br.readLine()) != null) {
        final int pct = (int)(pis.getProgress() * 100.0);
        // assume progressbar is final, etc.
        SwingUtilities.invokeLater(new Runnable() {
           public void run() {
                progressBar.setValue(pct);
           }
        });
    }
} catch(IOException e) {
    // do proper handling here.....
}
rolfl
  • 17,539
  • 7
  • 42
  • 76