簡體   English   中英

Java-閱讀編寫大型長數組代碼

[英]Java - Reading Writing Large Long Array Code

我正在嘗試將大小為400000000的大型長數組寫入文件,然后將其讀回。 我正在使用的代碼如下:

import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.io.RandomAccessFile ;
import java.util.* ;

class Checks {
public static FileChannel channel;
public static MappedByteBuffer mbb;

public static void main(String[] args){
    try{


      long k[] = new long[400000000] ;
          for(int i = 0 ; i < 400000000 ; i++){
            k[i] = i ;
          }

    channel = new RandomAccessFile("abc.dat", "rw").getChannel();
        mbb = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1 << 24);
        mbb.order(ByteOrder.nativeOrder());

          for(int i = 0 ; i < 400000000 ;i++ ){
             getMbb().putLong(k[i]);
        }

        channel.close();

       long ks[] = new long[400000000] ;

        channel = new RandomAccessFile("abc.dat", "rw").getChannel();
        mbb = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1 << 24);
        mbb.order(ByteOrder.nativeOrder());

        for(int r = 0 ; r < 400000000; r++){
            ks[r] = getMbb().getLong();
         }

             for(int r = 0 ; r < 400000000; r++){
                 if(k[r] != ks[r]){
                  System.out.println("Error at " + r);
                  break ;
                  }
              }


}
    catch(Exception e)
    {
        e.printStackTrace();
    }

   }

    public static ByteBuffer getMbb() throws IOException {
        if (mbb.remaining() <= 0) {
            mbb = channel.map(FileChannel.MapMode.READ_WRITE, channel.size(), 1 << 24);
            mbb.order(ByteOrder.nativeOrder());
        }
        return mbb;
    }
}

但是,此代碼給出了錯誤,即寫入和讀取數組不相同。 有人可以幫助我為什么會這樣嗎?

在關閉通道之前,請嘗試將對映射緩沖區所做的更改強制強制到磁盤上:

 mbb.force();

這樣,如果您正在使用存儲在本地設備上的文件,則可以保證對映射緩沖區所做的所有更改都將反映在磁盤上。

考慮到您僅追加到文件,完成所需內容的另一種方法是:

  channel = new RandomAccessFile("abc.dat", "rw").getChannel();

  ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE/8 * 1001);
  for(int i = 0 ; i < 400000000 ;i++ ){
     //write a number of byte to a ByteBuffer
      buffer.putLong(k[i]);
      if(i % 1000 == 0){
          channel.write(buffer);
          buffer.clear();
      }
   }
   channel.write(buffer);
   buffer.clear();

閱讀:

    buffer.clear();
    int bytesCnt;
    while((bytesCnt = channel.read(buffer))!=-1){
    for(int r = 0 ; r < bytesCnt; r++){
        ks[r] = buffer.getLong();
     }
    }

關於性能:在執行I / O的應用程序中,性能損失取決於搜索次數。 因此,搜尋次數越少,性能越高。 這等效於以順序方式寫入盡可能多的數據 (刷新次數較少的磁盤;刷新實際上是查找)。

在您的方案中,數據僅以順序方式寫入(追加到文件中),因此唯一需要擔心的方面是刷新到磁盤的次數。 此數字與緩沖區的大小成反比。 因此,您應該嘗試盡可能增加緩沖區的大小。

這是我的建議:

public static void main(String[] args) {

  File f = new File("abc.txt");

  DataOutputStream s = new DataOutputStream( new FileOutputStream(f));

  for ( int i = 0; i < 400000000; i++ ) {
    s.writeLong(i);
  }
  s.close();

  DataInputStream is = new DataInputStream( new FileInputStream(f));
  for (int i = 0; i < 400000000; i++ ) {
    if ( i != is.readLong() ) System.out.println("Error at " + i);
  }
}

這可以完成您程序的所有工作,但無需顯式分配內存,當然也無需通過內存映射的緩沖區復制該分配。 這種解決方案是否真正適用於您真正想做的事情,很難說,因為您沒有說這是為了什么。

我修改了一些代碼,以使用DataInputStreamDataOutputStream代替RandomAccessFile,它的工作原理很吸引人。

    try {
        long k[] = new long[400000000];
        for (int i = 0; i < k.length; i++) {
            k[i] = i;
        }

        DataOutputStream dos = new DataOutputStream(new FileOutputStream("abc.dat"));
        for (int i = 0; i < k.length; i++) {
            dos.writeLong(k[i]);
        }

        long ks[] = new long[k.length];

        DataInputStream dis = new DataInputStream(new FileInputStream("abc.dat"));

        for (int r = 0; r < ks.length; r++) {
            ks[r] = dis.readLong();
        }

        for (int r = 0; r < k.length; r++) {
            if (k[r] != ks[r]) {
                System.out.println("Error at " + r);
                break;
            }
        }
    } catch(Exception e) {
    } finally {
        // Make sure to close the streams
        dos.close();
        dis.close();
    }

我認為您的getMbb()方法已損壞。 每次重新映射內存中的文件塊時,都映射到channel.size() 僅在創建文件時有效,而在讀取文件時無效。 讀取文件時,將映射文件結尾之后的文件“區域”,該區域具有隨機內容。

您將必須修復重新映射代碼以跟蹤文件中已存在的位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM