Как я могу отслеживать чтение файла с помощью.readLine() в Java?

Я читаю файл с использованием BufferedREader, файл представляет собой текстовый файл с большим количеством текста

вот как я это читаю

 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;
                      }
                }

Я хочу отследить, какой процент файла я прочитал, чтобы я мог использовать это процентное значение в моем индикаторе прогресса следующим образом:

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

4 ответа

Решение

Есть много способов достичь этого, но вам нужно помнить четыре вещи...

  1. Вы должны знать, сколько вы читаете
  2. Вы должны знать, сколько вы прочитали
  3. Вы никогда не должны выполнять какие-либо действия в контексте потока диспетчеризации событий, которые могут его блокировать (такие как длительные циклы или блокировка ввода / вывода).
  4. Вы никогда не должны изменять или изменять состояние пользовательского интерфейса из какого-либо потока, кроме потока диспетчеризации событий.

Этот пример просто использует SwingWorker для чтения файла в фоновом потоке и использования его функциональности прогресса для публикации обновлений в контексте 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();
            }
        }

    }

}

Теперь вы можете включить SwingWorker с одной из других реализаций "ProgressInputStream" также. Посмотрите на Concurrency in Swing для более подробной информации

Используйте FileInputStream, javax.swing.ProgressMonitorInputStream, InputStreamReader и BufferedReader. Тогда все это происходит автоматически.

В качестве быстрого "хака" вы можете реализовать подсчет FilterInputStream и использовать его так, как предлагает EJP:

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;
    }

}

Затем ваш код может сделать:

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.....
}

Легко

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;
       }

  }

тогда просто используйте стандартные методы получения. Вы можете получить максимум, используя myInputStream.availble();

ссылка на соответствующий исходный код: http://developer.classpath.org/doc/javax/swing/ProgressMonitorInputStream-source.html

Другие вопросы по тегам