2009-07-15 7 views
1

Je construis un système en Java qui doit copier un sous-ensemble d'un fichier dans un autre fichier (pas nécessairement au début du fichier). C'est à dire. Je les paramètres suivants:Copie efficace d'un fichier à un autre

File srcFile, File dstFile, long srcFileOffset, long dstFileOffset, long length

Plusieurs threads peuvent être en train de lire à partir du même fichier source et d'écriture sur le même fichier de destination (mais avec des décalages différents) simultaneosuly donc j'ai besoin le processus d'être thread- sûr (c'est-à-dire empêcher d'autres threads de chercher dans le fichier pendant qu'un thread écrit/lit).

Comment implémenteriez-vous ceci? Dois-je utiliser un fichier RandomAccessFile ou Java NIO? Quel genre de serrures dois-je acquérir? Par exemple. Est-ce qu'une instance RandomAccessFile acquiert automatiquement un verrou système sur le fichier ou dois-je le conserver séparément? Editer: On dirait que randomAccessFile.getChannel().tryLock() acquiert un verrou à l'échelle du système, mais il est détenu par VM, pas le thread appelant. Donc, si j'utilise cela, je dois aussi acquérir un verrou pour le thread (ou deux en fait puisque j'ai besoin de verrouiller le fichier source et le fichier de destination).

Répondre

2

J'ai composé un petit code de test. Semble fonctionner sans problème sur Windows XP:

import java.io.RandomAccessFile; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class MultiRAF { 
    public static void main(String[] args) throws Exception { 
     RandomAccessFile raf = new RandomAccessFile("testraf.dat", "rw"); 
     raf.setLength(4096); 
     raf.close(); 
     ExecutorService exec = Executors.newCachedThreadPool(); 
     for (int k = 0; k < 4; k++) { 
      final int offset = k * 1024; 
      final int kid = k; 
      exec.submit(new Runnable() { 
       public void run() { 
        try { 
         RandomAccessFile raf = new RandomAccessFile(
          "testraf.dat", "rw"); 
         for (int j = 0; j < 100; j++) { 
          System.out.printf("%d accessing%n", kid); 
          byte[] data = new byte[1024]; 
          for (int i = 0; i < data.length; i++) { 
           data[i] = (byte)i; 
          } 
          raf.seek(offset); 
          raf.write(data); 
          System.out.printf("%d done%n", kid); 
         } 
         raf.close(); 
        } catch (Exception ex) { 
         System.err.printf("%d failed%n", kid); 
         ex.printStackTrace(); 
        } 

       }; 
      }); 
     } 
     exec.shutdown(); 
    } 
} 
+0

Intéressant, je suppose que la position définie par seek est locale pour l'instance RandomAccessFile. Je ne savais pas que vous pouviez ouvrir plusieurs instances avec un accès en écriture au même fichier tout en conservant des positions distinctes dans le descripteur. – Yrlec

1

vous pouvez ouvrir un FileInputStream juste sur SRCFILE, sauter (srcFileOffset), et lire à partir de là. Mais pour écrire sur le fichier de destination à un certain décalage, vous aurez besoin de RandomAccessFile. En ce qui concerne le verrouillage, vous pouvez utiliser un singleton pour lire/écrire à partir du fichier et synchroniser les méthodes de lecture/écriture sur votre objet.

+0

+1. Probablement, la rationalisation de l'accès aléatoire devrait également améliorer les performances des E/S. – akarnokd

+0

Merci, je vais essayer ça. Ensuite, j'ai juste besoin de stocker les données lues dans un tampon intermédiaire, donc je ne l'écris pas octet par octet dans le RandomAccessFile. – Yrlec

Questions connexes