2011-07-31 71 views
0

我想同時從兩個不同的位置讀取文件。我也想使用緩衝的I/O流來提高效率。我試圖解決我自己給定的Java API,但它不工作。任何人都會幫忙?我需要它進行外部合併排序。感謝幫助!如何在Java中的兩個不同位置訪問同一文件

+3

爲什麼要在兩個地方同時讀取文件? io蒸汽的代碼/異常堆棧痕跡在哪裏不起作用? – Jeffrey

+0

基本上我嘗試使用RandomAccessFile,然後將其包裝到: new DataInputStream(new BufferedInputStream(new FileInputStream(file.getFD()))); 其中文件是隨機訪問文件。每次我在不同的地方開始訪問文件塊時,我都在RandomAccessFile上使用了seek,然後創建了新的包裝器。 – nivwusquorum

回答

1

您需要創建一個RandomAccessFile,它基本上是C的內存映射文件的Java等價物。

這個我found an example

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) { 
} 

編輯,你說你不能使用RandomAccessFile,這是跳過上下通過文件的唯一途徑。如果沒有它就卡住了,那麼你必須按順序讀取文件,但這並不意味着你不能打開多個指向同一文件的指針進行讀取。

我把下面的測試/示例放在一起,它清楚地表明您可以用不同的讀指針打開文件「兩次」,並按順序將文件的兩半相加。同樣,如果你需要隨機存取,你必須使用一個RandomAccessFile,而這正是我建議,但在這裏你去:

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

噢,是的,我不允許記憶地圖:(這是爲大學的作業而設計的,我的uni有點遲鈍,如果允許內存映射,他們不知道如何限制內存。 – nivwusquorum

+0

你是什麼意思「restrict記憶」? –

0

什麼是從簡單的打開文件兩次,並與工作阻止你它好像是兩個獨立的文件?

 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(); 
    } 
相關問題