1.package download;import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Observable;/*
 * 执行具体下载任务的类
 */
class Download extends Observable implements Runnable {
private static final int MAX_BUFFER_SIZE = 1024; public static final String STATUSES[] = { "Downloading", "Pause",
"Complete", "Canceled", "ERROR" };
public static final int DOWNLOADING = 0;
public static final int PAUSED = 1;
public static final int COMPLETE = 2;
public static final int CANCELED = 3;
public static final int ERROR = 4;
/*
 * 目标文件的下载地址
 */
private URL url; /*
 * 目标文件的大小
 */
private int size; /*
 * 已下载的字节数
 */
private int downloaded; /*
 * 当前的下载状态
 */
private int status; /*
 * 构造函数,完成变量的初始化
 */
public Download(URL url) {
this.url = url;
size = -1;
downloaded = 0;
status = DOWNLOADING;
download();
} /*
 * 返回url
 */
public String getUrl() {
return url.toString();
}
public int getSize() {
return size;
}
/*
 * 返回下载进度
 */
public float getProgress() {
return ((float) downloaded / size) * 100;
} /*
 * 返回下载状态
 */
public int getStatus() {
return status;
} /*
 * 暂停
 */
public void pause() {
status = PAUSED;
stateChanged();
}
/*
 * 恢复
 */
public void resume() {
status = DOWNLOADING;
stateChanged();
download();
}
/*
 * 取消
 */
public void cancel() {
status = CANCELED;
stateChanged();
}
/*
 * 下载任务出错
 */
public void error() {
status = ERROR;
stateChanged();
}
/*
 * 增加一个线程,开始下载
 */
private void download() {
Thread thread = new Thread(this);
thread.start();
}
private String getFileName(URL url) {
String fileName = url.getFile();
return fileName.substring(fileName.lastIndexOf('/') + 1);
}
/*
 * 执行下载任务
 */
public void run() {
RandomAccessFile file = null;
InputStream stream = null;
try {
HttpURLConnection connection = (HttpURLConnection) url
.openConnection(); connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
connection.connect();
if (connection.getResponseCode() / 100 != 2) {
error();
}
int contentLength = connection.getContentLength();
if (contentLength < 1) {
error();
}
if (size == -1) {
size = contentLength;
stateChanged();
}
file = new RandomAccessFile(getFileName(url), "rw");
file.seek(downloaded);
stream = connection.getInputStream();
while (status == DOWNLOADING) {
byte buffer[];
if (size - downloaded > MAX_BUFFER_SIZE) {
buffer = new byte[MAX_BUFFER_SIZE];
} else {
buffer = new byte[size - downloaded];
} int read = stream.read(buffer); if (read == -1) {
break;
}
file.write(buffer, 0, read);
downloaded += read;
stateChanged();
}
if (status == DOWNLOADING) {
status = COMPLETE;
stateChanged();
}
} catch (Exception e) {
error();
} finally {
if (file != null) {
try {
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
e.printStackTrace();
}

}
}
/*
 * 通知observer,下载状态改变了
 */
private void stateChanged() {
setChanged();
notifyObservers();
}
}
2.package download;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JProgressBar;
import javax.swing.table.AbstractTableModel;
/*
 * 下载管理器的主要工作由Download类完成。Download类的主要
 工作是下载一个文件并将其内容保存到磁盘。每次向下载管理器
 添加一项下载任务时,就会有一个新的Download对象被实力化,
 以便处理这个下载任务。
 
 下载管理器具有同时下载多个文件的能力,而每个同时进行的下载任务都必须独立运行,
 且每个下载还必须管理自己的状态,以便反映在GUI中。这个工作也通过Download类来完成。
 */
class DownloadsTableModel extends AbstractTableModel implements Observer {
public static final long serialVersionUID = 223; private static final String[] columnNames = { "URL", "Size", "Progress",
"Status" };
private static final Class[] columnClasses = { String.class, String.class,
JProgressBar.class, String.class };
private ArrayList<Download> downloadList;
public DownloadsTableModel() {
downloadList = new ArrayList<Download>();
}
/*
 * 添加一个新的Download对象到下载任务列表中,表格因此新增一行
 */
public void addDownload(Download download) {
download.addObserver(this);
downloadList.add(download);
fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
}
public Download getDownload(int row) {
return downloadList.get(row);
}
/*
 * 从下载列表中删除一个Download
 */
public void clearDownload(int row) {
downloadList.remove(row);
fireTableRowsDeleted(row, row);
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Class<?> getColumnClass(int col) {
return columnClasses[col];
} public int getRowCount() {
return columnNames.length;
}
public Object getValueAt(int row, int col) {
try {
Download download = (Download) downloadList.get(row);
switch (col) {
case 0://
return download.getUrl();
case 1:
int size = download.getSize();
return (size == -1) ? "" : Integer.toString(size);
case 2:
return new Float(download.getProgress());
case 3:
return Download.STATUSES[download.getStatus()];
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public void update(Observable o, Object arg) { int index = downloadList.indexOf(o); fireTableRowsUpdated(index, index);
}}
3.package download;import java.awt.Component;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;/*
 * ProgressRenderer类是一个小小的工具类,
 *用于显示GUI的“Downloads”JTtable实例中的下载任务的进度
 */
class ProgressRenderer extends JProgressBar implements TableCellRenderer {
public static final long serialVersionUID = 23; public ProgressRenderer(int min, int max) {
super(min, max);
} public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
setValue((int) ((Float) value).floatValue());

return this;
}
}

解决方案 »

  1.   

    4.package download;import java.awt.BorderLayout;
    import java.awt.Container;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.net.URL;
    import java.util.Observable;
    import java.util.Observer;import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.ListSelectionModel;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;/*
     * 创建并运行下载管理器的GUI
     */
    public class DownloadManager extends JFrame implements Observer {
    public static final long serialVersionUID = 23; private JTextField url; private DownloadsTableModel tableModel; private JTable table;
    private JButton pauseButton, resumeButton;
    private JButton cancelButton, clearButton;
    private Download selectedDownload;
    private boolean clearing;
    JPanel addPanel;
    JPanel downloadPanel;
    JPanel buttonsPanel; public DownloadManager() {
    setTitle("Fans Download");
    setSize(640, 480);
    addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
    actionExit();
    }
    });
    initMenu();
    initPanel(); Container container = getContentPane();
    container.setLayout(new BorderLayout());
    container.setLayout(new BorderLayout());
    container.add(addPanel, BorderLayout.NORTH);
    container.add(downloadPanel, BorderLayout.CENTER);
    container.add(buttonsPanel, BorderLayout.SOUTH);
    } private void initMenu() {
    // 创建菜单
    JMenuBar menuBar = new JMenuBar();
    JMenu fileMenu = new JMenu("File");
    fileMenu.setMnemonic(KeyEvent.VK_F);
    JMenuItem fileExit = new JMenuItem("退出", KeyEvent.VK_X);
    fileExit.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    actionExit();
    }
    });
    fileMenu.add(fileExit);
    setJMenuBar(menuBar);
    } private void initPanel() { /*
     * 添加下载任务的面板
     */
    addPanel = new JPanel();
    url = new JTextField(30);
    addPanel.add(url);
    JButton addButton = new JButton("添加下载任务");
    addButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    actionAdd();
    }
    });
    addPanel.add(addButton); tableModel = new DownloadsTableModel();
    table = new JTable(tableModel);
    table.getSelectionModel().addListSelectionListener(
    new ListSelectionListener() {
    public void valueChanged(ListSelectionEvent e) {
    tableSelectionChanged();
    }
    }); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    ProgressRenderer renderer = new ProgressRenderer(0, 100);
    renderer.setStringPainted(true);
    table.setDefaultRenderer(JProgressBar.class, renderer);
    table.setRowHeight((int) renderer.getPreferredSize().getHeight()); /*
     * 下载面板
     */
    downloadPanel = new JPanel();
    downloadPanel.setBorder(BorderFactory.createTitledBorder("Downloads"));
    downloadPanel.setLayout(new BorderLayout());
    downloadPanel.add(new JScrollPane(table), BorderLayout.CENTER); /*
     * 按钮面板
     */
    buttonsPanel = new JPanel();
    pauseButton = new JButton("暂停");
    resumeButton = new JButton("恢复");
    cancelButton = new JButton("取消");
    clearButton = new JButton("清除");
    buttonsPanel.add(pauseButton);
    buttonsPanel.add(resumeButton);
    buttonsPanel.add(cancelButton);
    buttonsPanel.add(clearButton);
    }
    /*
     * 验证URL的有效性
     */
    private URL verifyUrl(String url) {
    if (!url.toLowerCase().startsWith("http://")) {
    return null;
    } URL verifiedUrl = null;
    try {
    verifiedUrl = new URL(url);
    } catch (Exception e) {
    e.printStackTrace();
    } if (verifiedUrl.getFile().length() < 2) {
    return null;
    }
    return verifiedUrl;
    }
    /*
     * 退出
     */
    private void actionExit() {
    System.exit(1);
    }
    /*
     * 增加
     */
    private void actionAdd() { URL verifiedUrl = verifyUrl(url.getText());
    if (verifiedUrl != null) {
    tableModel.addDownload(new Download(verifiedUrl));
    url.setText("");
    } else {
    JOptionPane.showMessageDialog(this, "Invalid Download URL",
    "Urror", JOptionPane.ERROR_MESSAGE);
    }
    }
    private void tableSelectionChanged() {
    if (selectedDownload != null) {
    selectedDownload.deleteObserver(DownloadManager.this);
    ;
    if (!clearing && table.getSelectedRow() > -1) {
    selectedDownload = tableModel.getDownload(table
    .getSelectedRow());
    selectedDownload.addObserver(DownloadManager.this);
    updateButtons();
    }}} /*
     * 暂停
     */
    private void actionPause() {
    selectedDownload.pause();
    updateButtons();
    }
    /*
     * 恢复
     */
    private void actionResume() {
    selectedDownload.resume();
    updateButtons();
    }
    /*
     * 取消下载任务
     */
    private void actionCancel() {
    selectedDownload.cancel();
    updateButtons();
    }
    private void actionClear() {
    clearing = true;
    tableModel.clearDownload(table.getSelectedRow());
    clearing = false;
    selectedDownload = null;
    updateButtons();
    } /*
     * 根据选定的下载项的状态更新按钮状态
     */
    private void updateButtons() {
    if (selectedDownload != null) {
    int status = selectedDownload.getStatus();
    switch (status) { case (Download.DOWNLOADING):
    pauseButton.setEnabled(true);
    resumeButton.setEnabled(false);
    cancelButton.setEnabled(true);
    clearButton.setEnabled(false);
    break;
    case Download.PAUSED:
    pauseButton.setEnabled(false);
    resumeButton.setEnabled(true);
    cancelButton.setEnabled(true);
    clearButton.setEnabled(false);
    break;
    case Download.ERROR:
    pauseButton.setEnabled(false);
    resumeButton.setEnabled(true);
    cancelButton.setEnabled(true);
    clearButton.setEnabled(false);
    break;
    default:
    pauseButton.setEnabled(false);
    resumeButton.setEnabled(false);
    cancelButton.setEnabled(false);
    clearButton.setEnabled(true);
    break;
    }
    } else {
    pauseButton.setEnabled(false);
    resumeButton.setEnabled(false);
    cancelButton.setEnabled(false);
    clearButton.setEnabled(false);
    }
    } public void update(Observable o, Object arg) {
    if (selectedDownload != null && selectedDownload.equals(o)) {
    updateButtons();
    }
    } public static void main(String[] args) {
    DownloadManager manager = new DownloadManager();
    manager.setVisible(true);
    }
    }
      

  2.   

             java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.RangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at download.DownloadsTableModel.getValueAt(DownloadsTableModel.java:96)