2011-09-13 5 views
0

Je télécharge des ensembles d'images dans des threads séparés et les enregistre sur la carte SD. Le problème est que lorsque j'exécute deux threads de téléchargement ou plus, les images sauvegardées sont corrompues. Si un seul thread est en cours d'exécution, les images sont ok. Je le télécharge depuis le même domaine mais avec une URL différente, par exemple. www.test.com/set1/img1.jpg, www.test.com/set2/img1.jpg etc.Les téléchargements simultanés entraînent des fichiers corrompus

Je les enregistre dans différents dossiers sous le nom de l'ensemble. J'ai remarqué que la plupart des images plus grandes sont corrompues (plus de 500 Ko), les plus petites sont généralement correctes, mais pas toujours.

Avez-vous la moindre idée de la raison pour laquelle les fichiers sont endommagés lorsque plusieurs threads sont en cours d'exécution?

est ici une partie du code que je utilise:

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 est coutume classe abstraite mise en œuvre Runnable. Et je l'utilise en fil de la manière habituelle:

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

J'appelle downloadIssuePages() sur deux objets différents pour télécharger deux jeux par exemple.

En utilisant la version SDK 11 (Android 3.0), appareil Acer Iconia Tab A500 avec Android 3.1

+0

J'ai une théorie pourquoi il pourrait se produire, lorsque vous utilisez des fils et ils peuvent parfois données overrite chacun des autres , en d'autres termes, ils peuvent écrire sur le même nom de fichier ou le même emplacement mémoire ou quelque chose comme ça, en général faire des choses comme ça, je conseille d'utiliser des verrous mais je ne sais pas sur les verrous pour ce que vous faites à mobile dev – Armand

+0

Merci pour un conseil, je suis arrivé à la même conclusion. Mais le fait est que ces threads écrivent dans des fichiers différents, donc ils ne devraient pas entrer en collision. Apparemment, il y a des collisions dans le flux de données des flux ou quoi. J'ai utilisé la serrure maintenant en écrivant au dossier et ressemble à cela fonctionne. – Speedy

Répondre

1

J'ai essayé de désactiver l'écriture pour le second fil, seul le premier fil était l'enregistrement des fichiers pour savoir s'il y a un problème de lecture du flux ou d'écriture. Apparemment, l'écriture était le problème car les données étaient correctes dans ce cas.

Je décide donc d'utiliser le verrouillage autour de l'écriture dans le fichier et ressemble à cela fonctionne très bien:

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