2010-06-23 4 views

ответ

9

Используйте javax.swing.ProgressMonitorInputStream.

+0

Я думаю, что это будет достаточно близко. Благодаря! – Danijel

+0

Может ли любой ответ быть проще? :) – Matthieu

1

Предполагая, что вы знаете, сколько статей у вас есть, не можете ли вы просто оставить счетчик в обработчике? Например.

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

(я не знаю, вы разбор «статьи», это просто пример)

Если вы не знаете номер статьи заранее, вам нужно будет считать его первым , Затем вы можете распечатать статус nb tags read/total nb of tags, скажем, каждые 100 тегов (counter % 100 == 0).

Или у вас есть еще одна нить, отслеживающая прогресс. В этом случае вам может понадобиться синхронизировать доступ к счетчику, но не обязательно, учитывая, что он не должен быть действительно точным.

Мои 2 цента

+0

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

2

Вы можете получить оценку текущей строки/столбца в файле путем переопределения метода setDocumentLocator из org.xml.sax.helpers.DefaultHandler/BaseHandler. Этот метод вызывается с объектом, из которого вы можете получить приближение текущей строки/столбца, когда это необходимо.

Редактировать: Насколько мне известно, стандартного способа получить абсолютное положение нет. Тем не менее, я уверен, что некоторые реализации SAX предлагают такую ​​информацию.

+0

Закрыть, но тогда мне нужно будет узнать количество строк в файле, не так ли? – Danijel

+0

Действительно. Другая идея могла бы быть указана загадочным EJP. Вы можете оценить прогресс, используя продвижение во входном потоке. Тем не менее, это не прогресс в анализе, из-за потенциальной буферизации и просмотра. –

0

Я хотел бы использовать положение входного потока. Создайте свой собственный тривиальный класс потока, который делегирует/наследует от «реального» и отслеживает чтение байтов. Как вы говорите, получить общий размер файла легко. Я бы не беспокоился о буферизации, поиске и т. Д. - для больших файлов, подобных этим, это курица. С другой стороны, я бы ограничил позицию «99%».

10

Благодаря предложению EJP ProgressMonitorInputStream, в конце я продлил FilterInputStream, так что ChangeListener может использоваться для контроля текущего местоположения чтения в терминах байтов.

С этим вы имеете более тонкое управление, например, чтобы показать несколько индикаторов выполнения для параллельного чтения больших файлов xml. Это именно то, что я сделал.

Таким образом, упрощенная версия отслеживаемых потока:

/** 
* 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); 
    } 
} 

Он не знает - или ухода - как большой основной поток, так что вам нужно, чтобы получить его другим способом, например, от самого файла.

Итак, здесь идет упрощенное использование образца:

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 

} 

В моем случае подвижки поднимают красиво слева направо без аномальных скачков. Отрегулируйте пороговое значение для оптимального баланса между производительностью и быстротой реагирования. Слишком мало, и скорость чтения может более чем удваиваться на небольших устройствах, слишком велика, и прогресс не будет плавным.

Надеюсь, это поможет. Не стесняйтесь редактировать, если вы обнаружили ошибки или опечатки, или проголосуйте, чтобы прислать мне некоторые поощрения!: D

+0

Отлично! Именно то, что я искал, я приспособию это, спасибо! :) – Matthieu

Смежные вопросы