0

我正在写一个小文件浏览器。我在下载文件实现方面有一个小问题。当我尝试取消下载并从列表中删除时,我收到此错误:

Exception in thread "Timer-2" java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
    at java.util.Vector.elementAt(Unknown Source)
    at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
    at pkg_main.CLS_Downloader$1.run(CLS_Downloader.java:151)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)

这是我的代码:

下载类:

public class CLS_Downloader extends Thread {

    private final String sDOWNLOAD_FOLDER = "descargas/";

    private Socket tSock;

    private ObjectInputStream tObjInStream;
    private ObjectOutputStream tObjOutStream;

    private JTable tTable;
    private int iIndex;

    private CLS_TransferTableModel tTransferModel;

    private Boolean bDownloaded;
    private Boolean bFailed;

    private long iReadCount = 0;
    private long iReadTotal = 0;
    private long lTotalSize = 0;
    private long lRemainSize = 0;

    private String sFileName;

    private JProgressBar tProgressBar;

    public CLS_Downloader(Socket tSock, JTable tTable, int iIndex) {
        this.tTable = tTable;
        this.iIndex = iIndex;
        this.tSock = tSock;
        this.bDownloaded = false;
        this.bFailed = false;

        this.tTransferModel = (CLS_TransferTableModel) tTable.getModel();

        try {
            this.tObjOutStream = new ObjectOutputStream(
                    this.tSock.getOutputStream());
            this.tObjOutStream.flush();
            this.tObjInStream = new ObjectInputStream(
                    this.tSock.getInputStream());

            this.start();
        } catch (IOException e) {
            this.bFailed = true;
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public JTable getTable() {
        return tTable;
    }

    public void setTable(JTable tTable) {
        this.tTable = tTable;
    }

    public int getiIndex() {
        return iIndex;
    }

    public void setiIndex(int iIndex) {
        this.iIndex = iIndex;
    }

    public Socket getSock() {
        return tSock;
    }

    public void setSock(Socket tSock) {
        this.tSock = tSock;
    }

    public String getFileName() {
        return sFileName;
    }

    public void setFileName(String sFileName) {
        this.sFileName = sFileName;
    }

    public long getTotalSize() {
        return lTotalSize;
    }

    public void setTotalSize(long lTotalSize) {
        this.lTotalSize = lTotalSize;
    }

    public Boolean isDownloaded() {
        return bDownloaded;
    }

    public void setDownloaded(Boolean bDownloaded) {
        this.bDownloaded = bDownloaded;
    }

    public Boolean isFailed() {
        return bFailed;
    }

    public void setFailed(Boolean bFailed) {
        this.bFailed = bFailed;
    }

    private void setTableValues() {
        this.tTransferModel.setValueAt(this.tSock.getInetAddress()
                .getHostAddress(), iIndex, 0);
        this.tTransferModel.setValueAt(this.sFileName, iIndex, 1);
        this.tTransferModel.setValueAt("Descargando", iIndex, 2);

        this.tProgressBar = (JProgressBar) tTable.getModel().getValueAt(
                this.iIndex, 3);
        this.tProgressBar.setStringPainted(true);

        this.tTransferModel.setValueAt(
                CLS_Functions.convertSize(this.lRemainSize), iIndex, 6);
    }

private void downloadComplete() {
        this.tProgressBar.setValue(100);
        this.tTable.repaint();
        this.tTransferModel.setValueAt("Completado", iIndex, 2);
        this.tTransferModel.setValueAt(CLS_Functions.convertSize(iReadTotal),
                iIndex, 4);
        this.tTransferModel.setValueAt(CLS_Functions.convertSize(lRemainSize),
                iIndex, 5);

        this.bDownloaded = true;
    }

    TimerTask tUpdateTable = new TimerTask() {
        public void run() {
            tProgressBar.setValue((int) ((iReadTotal * 100) / lTotalSize));
            tTable.repaint();
            tTransferModel.setValueAt(CLS_Functions.convertSize(iReadTotal),
                    iIndex, 4); //ERROR LINE
            tTransferModel.setValueAt(CLS_Functions.convertSize(lRemainSize),
                    iIndex, 5);
        }
    };

    public void run() {
        String sData = null;
        FileOutputStream tFileInStream = null;

        byte[] bArrRet = new byte[2048];

        try {
            sData = this.tObjInStream.readUTF();

            this.sFileName = new File(sData.split("#")[0]).getName();
            this.lTotalSize = Long.parseLong(sData.split("#")[1]);
            this.lRemainSize = this.lTotalSize;

            this.setTableValues();
            new Timer().scheduleAtFixedRate(tUpdateTable, 0, 1000);

            tFileInStream = new FileOutputStream(sDOWNLOAD_FOLDER + this.sFileName);

            while (this.lRemainSize > 0) {
                this.iReadCount = tObjInStream.read(bArrRet);
                tFileInStream.write(bArrRet, 0, (int) this.iReadCount);
                tFileInStream.flush();
                this.lRemainSize -= this.iReadCount;
                this.iReadTotal += this.iReadCount;

                Thread.sleep(5);
            }

            this.tUpdateTable.cancel();
            this.downloadComplete();
            tFileInStream.close();
            this.close();

            System.out.println("listo");

        } catch (Exception e) {
            // TODO Auto-generated catch block
            try {
                tFileInStream.close();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            this.close();
            this.bFailed = true;
            this.tTransferModel.setValueAt("Fallado", iIndex, 2);
            this.tUpdateTable.cancel();
        }
    }

    public void close() {
        try {
            this.tUpdateTable.cancel();
            this.tObjOutStream.close();
            this.tObjInStream.close();
            this.tSock.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

下载管理器类:

public class CLS_DownloadManager {

    private static CLS_DownloadManager tDownloadManager;
    private ArrayList<CLS_Downloader> tDownloadList = new ArrayList<CLS_Downloader>();

    public static CLS_DownloadManager getInstance() {
        if (tDownloadManager == null)
            tDownloadManager = new CLS_DownloadManager();

        return tDownloadManager;
    }

    public ArrayList<CLS_Downloader> getDownloadList() {
        return tDownloadList;
    }

    public void setDownloadList(ArrayList<CLS_Downloader> tDownloadList) {
        this.tDownloadList = tDownloadList;
    }

    public void addDownload(CLS_Downloader tDownload) {
        this.tDownloadList.add(tDownload);
    }

    public CLS_Downloader getDownload(int iIndex) {
        return this.tDownloadList.get(iIndex);
    }

    public void deleteDownload(int iIndex) {
        this.tDownloadList.remove(iIndex);
    }

    public void deleteDownload(CLS_Downloader tDownload) {
        this.tDownloadList.remove(tDownload);
    }

    public void cancelDownload(int iIndex) {
        this.tDownloadList.get(iIndex).close();
    }

    public void cleanDownloads() {
        for (int i = this.tDownloadList.size() - 1; i >= 0; i--)
            if (this.tDownloadList.get(i).isDownloaded()
                    || this.tDownloadList.get(i).isFailed())
                this.tDownloadList.remove(i);
    }

    public int getListCount() {
        return this.tDownloadList.size();
    }
}

下载取消功能:

if (TBL_Downloads.getSelectedRow() > -1) {
    CLS_DownloadManager.getInstance().cancelDownload(TBL_Downloads.getSelectedRow());
}

提前致谢!

4

1 回答 1

2

您的设计将业务对象(CLS_Downloader)与视图(JTable 及其表模型)混合在一起。

我在这里看到的问题是您的 CLS_Downloader 引用了表模型,更重要的是它的索引。除此之外,您还可以在 CLS_DownloadManager 内的列表中跟踪您的下载。

当您更新数据(通过取消下载)时,使所有内容保持同步变得复杂(表模型、CLS_DownloadManager、所有 CLS_Downloader 中的索引)。

查找模型视图控制器架构以更好地组织代码。在你的情况下,模型应该是 CLS_Downloader,视图应该是 JTable,控制器应该是 CLS_DownloadManager

于 2013-07-15T20:29:51.743 回答