---
category: swing
folder: ProgressMonitorInputStream
title: ProgressMonitorInputStreamを使用してテキストファイルのダウンロード状況を表示
tags: [ProgressMonitorInputStream, ProgressMonitor, JProgressBar, SwingWorker, URLConnection, JTextArea]
author: aterai
pubdate: 2013-04-22T03:35:42+09:00
description: ProgressMonitorInputStreamを使用してテキストファイルのダウンロード状態を進捗表示します。
image: https://lh4.googleusercontent.com/-gXnU23f7iiw/UXQuzmKdfVI/AAAAAAAABp8/aPk0QR78NlY/s800/ProgressMonitorInputStream.png
---
* Summary [#summary]
`ProgressMonitorInputStream`を使用してテキストファイルのダウンロード状態を進捗表示します。
#download(https://lh4.googleusercontent.com/-gXnU23f7iiw/UXQuzmKdfVI/AAAAAAAABp8/aPk0QR78NlY/s800/ProgressMonitorInputStream.png)
* Source Code Examples [#sourcecode]
#code(link){{
class RunAction extends AbstractAction {
public RunAction() {
super("Load");
}
@Override public void actionPerformed(ActionEvent e) {
runButton.setEnabled(false);
textArea.setText("");
URLConnection urlConnection = getURLConnection();
if (urlConnection == null) {
return;
}
Charset cs = getCharset(urlConnection, "UTF-8");
int length = urlConnection.getContentLength();
JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(
(Component) e.getSource());
try {
InputStream is = urlConnection.getInputStream();
ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(
frame, "Loading", is);
monitor = pmis.getProgressMonitor();
monitor.setNote(" "); //Need for JLabel#getPreferredSize
monitor.setMillisToDecideToPopup(0);
monitor.setMillisToPopup(0);
monitor.setMinimum(0);
monitor.setMaximum(length);
worker = new MonitorTask(pmis, cs, length);
worker.execute();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private class MonitorTask extends Task {
public MonitorTask(ProgressMonitorInputStream pmis, Charset cs, int length) {
super(pmis, cs, length);
}
@Override protected void process(List<Chunk> chunks) {
for (Chunk c : chunks) {
textArea.append(c.line + "\n");
monitor.setNote(c.note);
}
textArea.setCaretPosition(textArea.getDocument().getLength());
}
@Override public void done() {
runButton.setEnabled(true);
String text = null;
try {
if (pmis != null) {
pmis.close();
}
text = isCancelled() ? "Cancelled" : get();
} catch (IOException | InterruptedException | ExecutionException ex) {
ex.printStackTrace();
text = "Exception";
}
System.out.println(text);
}
}
private static class Task extends SwingWorker<String, Chunk> {
protected final ProgressMonitorInputStream pmis;
protected final Charset cs;
protected final int length;
public Task(ProgressMonitorInputStream pmis, Charset cs, int length) {
super();
this.pmis = pmis;
this.cs = cs;
this.length = length;
}
@Override public String doInBackground() {
String ret = "Done";
try (Scanner scanner = new Scanner(
new BufferedReader(new InputStreamReader(pmis, cs)))) {
int i = 0;
int size = 0;
while (scanner.hasNextLine()) {
if (i % 50 == 0) { //Wait
Thread.sleep(10);
}
i++;
String line = scanner.nextLine();
size += line.getBytes(cs).length + 1; //+1: \n
String note = String.format(
"%03d%% - %d/%d%n", 100 * size / length, size, length);
//System.out.println(note);
publish(new Chunk(line, note));
}
} catch (InterruptedException | IOException ex) {
System.out.println("Exception");
ret = "Exception";
cancel(true);
}
return ret;
}
}
}}
* Description [#explanation]
* Description [#description]
上記のサンプルでは、`URLConnection`から開いた`InputStream`に`ProgressMonitorInputStream`をラップして、ファイルのダウンロード進捗状態を`ProgressMonitor`で表示しています。
- `ProgressMonitorInputStream`の使用する`ProgressMonitor`の最大値はファイルサイズ(バイト)
-- `ProgressMonitorInputStream`がデフォルトで設定する最大値は`InputStream#available()`の値
-- この値がダウンロード中のストリームの合計バイト数を返す訳ではないので、これを最大値のままにしておくと`ProgressMonitor`が表示されない場合がある
-- `URLConnection#getContentLength()`で取得したバイト数を`ProgressMonitor#setMaximum(...)`で設定
- `1`行ずつ`JTextArea`に文字列として読み込ませるために`InputStreamReader`を使用しているので、エンコーディングを`URLConnection#getContentEncoding()`や`URLConnection#getContentType()`などで取得
-- 何パーセント読み込んだかを`ProgressMonitor#setNote(...)`で表示する場合は`1`行が何バイトかを`String#getBytes(Charset)`で取得して計算
-- このサンプルでは改行は`LF`のみの`1`バイトであると決め打ちしている
-- 進捗を表示する前に`ProgressMonitor#setNote("temp note");`と適当な文字列を設定しておかないと`Note`に使用する`JLabel`が`null`のままで表示されない、またはレイアウトがおかしくなる
* Reference [#reference]
- [[ProgressMonitorがダイアログを表示するまでの待ち時間>Swing/MillisToDecideToPopup]]
* Comment [#comment]
#comment
- `EDT`外で`ProgressMonitor`を変更する(`monitor.setMinimum(0);`など)のは駄目な気がするので、修正。 -- &user(aterai); &new{2014-02-04 (火) 15:05:59};
#comment