同时下载会导致文件损坏

时间:2011-09-13 12:58:29

标签: android multithreading

我在分离的线程中下载图像集并将它们保存到SD卡。问题是,当我运行两个或更多下载线程时,保存的图像已损坏。如果只有一个线程正在运行,那么图像就可以了。我是从同一个域下载它但不同的网址,例如www.test.com/set1/img1.jpg,www.test.com/set2/img1.jpg等。

我是通过集合的名称将它们保存到不同的文件夹中。我注意到大多数较大的图像已损坏(超过500 KB),较小的图像通常都可以,但并非总是如此。

您是否知道多个线程运行时文件被损坏的原因?

以下是我正在使用的代码的一部分:

protected class DownloadTask extends DownloadRunnable {

    @Override
    public void run() {
        InputStream is = null;
        OutputStream os = null;
        File bitmapFile = null;
        /** some more declarations and preparations are here */

        for (int pg=getDownloadedPages(); pg < numPages; ++pg) {

            for (char ch='a'; ch <= 'e'; ++ch) {
                /* check for pause */
                synchronized (pauseLock) {
                    while (paused && !aborted) {
                        try {
                            pauseLock.wait();
                        } catch (InterruptedException e) {
                        }                               
                    }
                }
                fileName = "page-" + df.format(pg) + "-" + ch;                          
                url = MainApp.getRestrictedUrl(MainApp.tstcode, urlFile + fileName+ ".jpg");                            
                is = new BufferedInputStream(new URL(url).openStream());

                if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
                    bitmapFile = new File(pathToSave,  fileName + MagazinePage.FILE_EXT);
                    MainApp.encryptToFile(bitmapFile, is);
                    dwnlSize += bitmapFile.length();
                }
                is.close();
            }
        }
    }

    public static void encryptToFile(File file, InputStream is) throws IOException {        
    BufferedOutputStream os = null;
        try {
            if (file.exists()) {
                file.delete();
            } else {
                file.getParentFile().mkdirs();
            }
            file.createNewFile();
            os = new BufferedOutputStream(new FileOutputStream(file));
            IkioskContentProvider.getInstance().encrypt(is, os);
        } finally {
            os.close();
        }
    }
}

DownloadRunnable是实现Runnable的自定义抽象类。我正在常规方式使用它:

protected void downloadIssuePages() {
    dwnlTask = new DownloadTask();
    new Thread(dwnlTask).start();
}

我在两个不同的对象上调用downloadIssuePages()来下载两个例子。

使用SDK版本11(Android 3.0),设备Acer Iconia Tab A500与Android 3.1

1 个答案:

答案 0 :(得分:1)

我试图禁用第二个线程的写入,只有第一个线程正在保存文件以查明从流中读取或写入时是否存在问题。显然写作是问题,因为在这种情况下数据是正确的。

所以我决定使用lock来写文件,看起来它工作正常:

synchronized (MainApp.fileWritingLockObj) {
    while (MainApp.fileWritingLocked) {
        try {
            MainApp.fileWritingLockObj.wait();
        } catch (InterruptedException e) {
        }                               
    }
    MainApp.fileWritingLocked = true;                           
    if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
        bitmapFile = new File(pathToSave,  fileName + MagazinePage.FILE_EXT);
        MainApp.encryptToFile(bitmapFile, is);
        dwnlSize += bitmapFile.length();
    }
    is.close();
    MainApp.fileWritingLocked = false;
    MainApp.fileWritingLockObj.notifyAll();
}