2011-07-31 4 views
0

Je souhaite lire le fichier à partir de deux endroits différents simultanément. Je veux aussi utiliser un flux d'E/S tamponné pour l'efficacité. J'ai essayé de travailler sur mon propre API java, mais ça ne marche pas. Quelqu'un va t'aider? J'en ai besoin pour le tri externe de fusion. Merci pour l'aide!Comment accéder au même fichier à deux endroits différents dans Java

+3

Pourquoi voulez-vous lire un fichier à deux endroits en même temps? Où les traces de pile de code/d'exception de la vapeur io ne fonctionnent-elles pas? – Jeffrey

+0

Fondamentalement, j'ai essayé d'utiliser RandomAccessFile, puis l'envelopper dans: nouveau DataInputStream (nouveau BufferedInputStream (nouveau FileInputStream (fichier.getFD()))); Où fichier est un fichier d'accès aléatoire. Chaque fois que j'ai commencé à accéder au bloc de fichier à un endroit différent, j'ai cherché sur RandomAccessFile puis j'ai créé un nouveau wrapper. – nivwusquorum

Répondre

1

Vous devez créer un RandomAccessFile, qui est l'équivalent de Java du fichier mappé en mémoire de C.

Je found an example de ceci:

try { 
    File file = new File("filename"); 

    // Create a read-only memory-mapped file 
    FileChannel roChannel = new RandomAccessFile(file, "r").getChannel(); 
    ByteBuffer roBuf = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, (int)roChannel.size()); 

    // Create a read-write memory-mapped file 
    FileChannel rwChannel = new RandomAccessFile(file, "rw").getChannel(); 
    ByteBuffer wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, (int)rwChannel.size()); 

    // Create a private (copy-on-write) memory-mapped file. 
    // Any write to this channel results in a private copy of the data. 
    FileChannel pvChannel = new RandomAccessFile(file, "rw").getChannel(); 
    ByteBuffer pvBuf = roChannel.map(FileChannel.MapMode.READ_WRITE, 0, (int)rwChannel.size()); 
} catch (IOException e) { 
} 

Edition, vous avez dit que vous ne pouvez pas utiliser un RandomAccessFile, qui est la seule façon de sauter de haut en bas dans le fichier. Si vous êtes bloqué sans cela, vous devez lire le fichier séquentiellement, mais cela ne signifie pas que vous ne pouvez pas ouvrir plusieurs pointeurs sur le même fichier pour le lire.

J'ai assemblé le test/échantillon suivant et il montre clairement que vous pouvez ouvrir le fichier "deux fois" avec différents pointeurs de lecture et additionner séquentiellement deux moitiés du fichier. Encore une fois, si vous avez besoin accès aléatoire, vous devez utiliser un RandomAccessFile, et c'est ce que je vous suggère, mais ici vous allez:

public class FileTest { 

    public static void main(String[] args) throws IOException, InterruptedException, ExecutionException{ 

     File temp = File.createTempFile("asfd", ""); 
     BufferedWriter wrt = new BufferedWriter(new FileWriter(temp)); 

     int testLength = 10000; 
     int numWidth = String.valueOf(testLength).length(); 

     int targetSum = 0; 
     for(int i = 0; i < testLength; i++){ 
      // each line guaranteed to have a good number of characters for our test 
      wrt.write(String.format("%0"+ numWidth +"d\n", i)); 
      targetSum += i; 
     } 
     wrt.close(); 

     BufferedReader rdr1 = new BufferedReader(new FileReader(temp)); 
     BufferedReader rdr2 = new BufferedReader(new FileReader(temp)); 

     rdr2.skip((numWidth+1)*testLength/2); // skip first half of the lines 

     Summer sum1 = new Summer(rdr1, testLength/2); 
     Summer sum2 = new Summer(rdr2, testLength/2); 

     ExecutorService executor = Executors.newFixedThreadPool(2); 
     Future<Integer> halfSum1 = executor.submit(sum1); 
     Future<Integer> halfSum2 = executor.submit(sum2); 

     System.out.println("Total sum = " + (halfSum1.get() + halfSum2.get()) + " reference " + targetSum); 

     rdr1.close(); 
     rdr2.close(); 

     temp.delete(); 
    } 

    private static class Summer implements Callable<Integer>{ 
     private BufferedReader rdr; 
     private int limit; 

     public Summer(BufferedReader rdr, int limit) throws IOException{ 
      this.rdr = rdr; 
      this.limit = limit; 
     } 

     @Override 
     public Integer call() throws Exception { 
      System.out.println(Thread.currentThread().getName() + " started " + System.currentTimeMillis()); 
      int sum = 0; 
      for(int i = 0; i < limit; i++){ 
       sum += Integer.valueOf(rdr.readLine()); 
       // uncomment to see interleaving of threads: 
       //System.out.println(Thread.currentThread().getName()); 
      } 
      System.out.println(Thread.currentThread().getName() + " finished " + System.currentTimeMillis()); 
      return sum; 
     } 

    } 

} 
+0

Oh, ouais, je n'ai pas le droit de mapper la mémoire :(C'est pour l'attribution d'une université Mon université est un peu retardée et ne sait pas comment restreindre la mémoire si la carte mémoire est permise – nivwusquorum

+0

Que voulez-vous dire? Mémoire"? –

0

Qu'est-ce qui vous empêche d'ouvrir simplement le fichier deux fois, et travailler avec comme si c'était deux fichiers indépendants?

 File inputFile = new File("src/SameFileTwice.java"); 
    BufferedReader in1 = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile))); 
    BufferedReader in2 = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile))); 
    try { 
     String strLine; 
     while ((strLine = in1.readLine()) != null && (strLine = in2.readLine()) != null) { 
      System.out.println(strLine); 
     } 
    } finally { 
     in1.close(); 
     in2.close(); 
    } 
Questions connexes