2010-06-23 31 views

Trả lời

9

Sử dụng số javax.swing.ProgressMonitorInputStream.

+0

Tôi nghĩ điều này sẽ đủ gần. Cảm ơn! – Danijel

+0

Câu trả lời có thể đơn giản hơn thế không ?! :) – Matthieu

1

Giả sử bạn biết bạn có bao nhiêu bài viết, bạn có thể giữ một bộ đếm trong bộ xử lý không? Ví dụ.

public void startElement (String uri, String localName, 
          String qName, Attributes attributes) 
          throws SAXException { 
    if(qName.equals("article")){ 
     counter++ 
    } 
    ... 
} 

(Tôi không biết liệu bạn đang phân tích "bài viết", nó chỉ là một ví dụ)

Nếu bạn không biết số lượng các bài viết trước, bạn sẽ cần phải đếm nó đầu tiên . Sau đó, bạn có thể in trạng thái nb tags read/total nb of tags, giả sử mỗi thẻ 100 (counter % 100 == 0).

Hoặc thậm chí có một luồng khác theo dõi tiến độ. Trong trường hợp này, bạn có thể muốn đồng bộ hóa quyền truy cập vào bộ đếm, nhưng không cần thiết vì nó không cần phải thực sự chính xác.

2 cent Mỹ

+0

Tôi đã tìm ra điều đó, nhưng tôi đang tìm cách để làm điều đó mà không cần đếm các bài viết trước. Tôi nghĩ có thể có một cách để tìm ra vị trí của trình phân tích cú pháp trong tệp thay vì, tôi có thể dễ dàng nhận được kích thước tệp. – Danijel

2

Bạn có thể nhận được một ước tính của dòng/cột hiện tại trong tập tin của bạn bằng cách ghi đè các phương pháp setDocumentLocator của org.xml.sax.helpers.DefaultHandler/BaseHandler. Phương thức này được gọi với một đối tượng mà từ đó bạn có thể nhận được một xấp xỉ của dòng/cột hiện tại khi cần thiết.

Chỉnh sửa: Theo hiểu biết tốt nhất của tôi, không có cách nào tiêu chuẩn để có được vị trí tuyệt đối. Tuy nhiên, tôi chắc chắn một số triển khai SAX cung cấp loại thông tin này.

+0

Đóng, nhưng sau đó tôi sẽ phải biết số dòng trong tệp, phải không? – Danijel

+0

Thật vậy. Một ý tưởng khác có thể đã được chỉ ra bởi EJP bí ẩn. Bạn có thể ước tính tiến độ, bằng cách sử dụng tiến bộ trong luồng đầu vào. Tuy nhiên, đây cũng không phải là tiến bộ trong phân tích cú pháp, bởi vì tiềm năng đệm và lookaheads. –

0

Tôi muốn sử dụng vị trí luồng đầu vào. Làm cho lớp dòng tầm thường của bạn đại diện/kế thừa từ một "thực" và theo dõi các byte đọc. Như bạn nói, việc tổng số tệp được dễ dàng. Tôi sẽ không lo lắng về việc lưu vào bộ đệm, xem xét, vv - đối với các tệp lớn như thế này, đó là nguồn cấp dữ liệu cho gà. Mặt khác, tôi sẽ giới hạn vị trí thành "99%".

10

Nhờ đề xuất của EJP là ProgressMonitorInputStream, cuối cùng tôi mở rộng FilterInputStream để có thể sử dụng ChangeListener để theo dõi vị trí đọc hiện tại theo byte.

Với điều này bạn có quyền kiểm soát tốt hơn, ví dụ để hiển thị nhiều thanh tiến trình để đọc song song các tệp xml lớn. Đó là chính xác những gì tôi đã làm.

Vì vậy, một phiên bản đơn giản của con suối có thể giám sát:

/** 
* A class that monitors the read progress of an input stream. 
* 
* @author Hermia Yeung "Sheepy" 
* @since 2012-04-05 18:42 
*/ 
public class MonitoredInputStream extends FilterInputStream { 
    private volatile long mark = 0; 
    private volatile long lastTriggeredLocation = 0; 
    private volatile long location = 0; 
    private final int threshold; 
    private final List<ChangeListener> listeners = new ArrayList<>(4); 


    /** 
    * Creates a MonitoredInputStream over an underlying input stream. 
    * @param in Underlying input stream, should be non-null because of no public setter 
    * @param threshold Min. position change (in byte) to trigger change event. 
    */ 
    public MonitoredInputStream(InputStream in, int threshold) { 
     super(in); 
     this.threshold = threshold; 
    } 

    /** 
    * Creates a MonitoredInputStream over an underlying input stream. 
    * Default threshold is 16KB, small threshold may impact performance impact on larger streams. 
    * @param in Underlying input stream, should be non-null because of no public setter 
    */ 
    public MonitoredInputStream(InputStream in) { 
     super(in); 
     this.threshold = 1024*16; 
    } 

    public void addChangeListener(ChangeListener l) { if (!listeners.contains(l)) listeners.add(l); } 
    public void removeChangeListener(ChangeListener l) { listeners.remove(l); } 
    public long getProgress() { return location; } 

    protected void triggerChanged(final long location) { 
     if (threshold > 0 && Math.abs(location-lastTriggeredLocation) < threshold) return; 
     lastTriggeredLocation = location; 
     if (listeners.size() <= 0) return; 
     try { 
     final ChangeEvent evt = new ChangeEvent(this); 
     for (ChangeListener l : listeners) l.stateChanged(evt); 
     } catch (ConcurrentModificationException e) { 
     triggerChanged(location); // List changed? Let's re-try. 
     } 
    } 


    @Override public int read() throws IOException { 
     final int i = super.read(); 
     if (i != -1) triggerChanged(location++); 
     return i; 
    } 

    @Override public int read(byte[] b, int off, int len) throws IOException { 
     final int i = super.read(b, off, len); 
     if (i > 0) triggerChanged(location += i); 
     return i; 
    } 

    @Override public long skip(long n) throws IOException { 
     final long i = super.skip(n); 
     if (i > 0) triggerChanged(location += i); 
     return i; 
    } 

    @Override public void mark(int readlimit) { 
     super.mark(readlimit); 
     mark = location; 
    } 

    @Override public void reset() throws IOException { 
     super.reset(); 
     if (location != mark) triggerChanged(location = mark); 
    } 
} 

Nó không biết - hoặc chăm sóc - lớn như thế nào dòng cơ bản là, vì vậy bạn cần phải nhận được nó một cách khác, chẳng hạn như từ chính tệp đó.

Vì vậy, ở đây đi việc sử dụng mẫu đơn giản:

try (
    MonitoredInputStream mis = new MonitoredInputStream(new FileInputStream(file), 65536*4) 
) { 

    // Setup max progress and listener to monitor read progress 
    progressBar.setMaxProgress((int) file.length()); // Swing thread or before display please 
    mis.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { 
     SwingUtilities.invokeLater(new Runnable() { @Override public void run() { 
     progressBar.setProgress((int) mis.getProgress()); // Promise me you WILL use MVC instead of this anonymous class mess! 
     }}); 
    }}); 
    // Start parsing. Listener would call Swing event thread to do the update. 
    SAXParserFactory.newInstance().newSAXParser().parse(mis, this); 

} catch (IOException | ParserConfigurationException | SAXException e) { 

    e.printStackTrace(); 

} finally { 

    progressBar.setVisible(false); // Again please call this in swing event thread 

} 

Trong trường hợp của tôi tiến bộ nâng cao độc đáo từ trái sang phải mà không nhảy bất thường. Điều chỉnh ngưỡng để cân bằng tối ưu giữa hiệu suất và khả năng phản hồi. Quá nhỏ và tốc độ đọc có thể nhiều hơn sau đó tăng gấp đôi trên các thiết bị nhỏ, quá lớn và tiến trình sẽ không được mịn màng.

Hy vọng điều đó sẽ hữu ích. Vui lòng chỉnh sửa nếu bạn tìm thấy lỗi hoặc lỗi chính tả hoặc bỏ phiếu để gửi cho tôi một số khuyến khích!: D

+0

Tuyệt vời! Chính xác những gì tôi đang tìm kiếm, tôi sẽ thích ứng với điều đó, cảm ơn! :) – Matthieu

Các vấn đề liên quan