Domanda

I'm writting a small file browser. I have a small problem with downloading files implementation. When I try to cancel the download and delete from the list, i get this error:

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)

And this my code:

Download class:

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();
        }
    }
}

Downloads Manager class:

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();
    }
}

Download cancel function:

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

Thanks in advance!

È stato utile?

Soluzione

Your design is mixing the business objects (the CLS_Downloader) with the view (the JTable and its table model).

The problem I see here is that your CLS_Downloader has a reference to the table model and, more importantly to it's index in it. On top of that you also keep track of your downloads in a list inside the CLS_DownloadManager.

When you update the data (by cancelling a download) it becomes complicated to keep everything in sync (the table model, the CLS_DownloadManager, the indices in all the CLS_Downloader).

Look up the model view controller architecture for a better way to organize your code. In yor case, the model should be the CLS_Downloader, the view should be the JTable and the controller should be the CLS_DownloadManager

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top