【问题标题】:How do I track reading of a a file using .readLine() in java?如何在 java 中使用 .readLine() 跟踪文件的读取?
【发布时间】:2013-11-07 01:56:30
【问题描述】:

我正在使用 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;
                      }
                }

【问题讨论】:

标签: java swing file-io bufferedreader jprogressbar


【解决方案1】:

使用 FileInputStream、javax.swing.ProgressMonitorInputStream、InputStreamReader 和 BufferedReader。然后这一切都会自动发生。

【讨论】:

  • 问题在于它打开了自己的进度条,我想将值添加到我已经实例化的进度条中
  • @Snedden27 不要打扰。使用内置的。
  • 那么你必须提前计算行数或以字节为单位报告进度。
  • ProgressMonitorInputStream 背后的代码不可能那么复杂......它只是输入流上的一个过滤器......
  • hmm 现在我只是读取行数并将当前行除以总数,在 3 小时内到期,稍后可能会探索,感谢您的 cmets tho
【解决方案2】:

有很多方法可以实现这一点,但您需要牢记四件事...

  1. 您需要知道自己阅读了多少
  2. 你需要知道你读了多少
  3. 您不应该在事件调度线程的上下文中执行任何可能阻塞它的操作(例如长时间运行的循环或阻塞 I/O)
  4. 您不应该从除事件调度线程之外的任何线程修改或更改 UI 的状态

此示例仅使用 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

【讨论】:

    【解决方案3】:

    简单

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

    然后只需使用标准的 getter 方法。您可以通过使用 myInputStream.availble(); 来获得最大值;

    相关源码链接:http://developer.classpath.org/doc/javax/swing/ProgressMonitorInputStream-source.html

    【讨论】:

    • 我不相信availble 是衡量可能通过输入流的总内容的可靠度量
    • 这就是 ProgressMonitorInputStream 类所使用的。
    • 来自 JavaDocs “返回一个估计的字节数,可以从这个输入流中读取(或跳过)而不会被下一次调用这个输入流的方法阻塞” - 文件流可能不同,我只是说 ;)
    • 随时致电 Oracle 并要求他们更改 JDK。 :) 或者为 OpenJDK 做贡献
    • 别担心,同时,请随时提供可行的解决方案;)
    【解决方案4】:

    作为一种快速的“hack”,您可以实现一个计数 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.....
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-10
      • 2021-11-22
      相关资源
      最近更新 更多