MappedByteBuffer - BufferOverflowException

时间:2017-07-15 06:41:16

标签: java memory-mapped-files mappedbytebuffer

我正在使用MappedByteBuffer将记录写入文件。以下是我的代码。当我增加要写入的numberOfRows时,它会抛出BufferOverflowException。它适用于1000万numberOfRows。如果我将numberOfRows增加到1亿,则抛出BufferOverlowException!?

public static void writeOneFile() throws IOException{
     File file = File.createTempFile("outputfile", ".txt", new File("C:\\Data\\Output"));
     //f.delete();
     RandomAccessFile fileAccess = new RandomAccessFile(file, "rw");
     FileChannel fileChannel = fileAccess.getChannel();

     long bufferSize = (long) (Math.pow(10240, 2));//(long)(Math.pow(30720, 2));//(long) (Math.pow(1024, 2));//(long)Integer.MAX_VALUE;
     MappedByteBuffer mappedBuffer = fileChannel.map( FileChannel.MapMode.READ_WRITE, 0, bufferSize );

     long startPosMappedBuffer = 0;
     long million = 1000000; 
     long numberOfRows = million * 100; //million * 200 ;//1000;//million * 200 ; //200 million

     long startTime = System.currentTimeMillis();

     long counter = 1;
     //byte[] messageBytes = (counter+"").getBytes(Charset.forName("UTF-8"));
     //long bufferSize = (counter + "\n").getBytes(Charset.forName("UTF-8")).length * 1000;
     while(true)
     {         
         if( !mappedBuffer.hasRemaining() )
         {
             startPosMappedBuffer += mappedBuffer.position();
             mappedBuffer = fileChannel.map( FileChannel.MapMode.READ_WRITE, startPosMappedBuffer, bufferSize );
         }
         mappedBuffer.put( (counter + System.lineSeparator()).getBytes(Charset.forName("UTF-8")) ); //+ System.lineSeparator() //putLong( counter ); // ); 
         //mappedBuffer.rewind();

         counter++;
         if( counter > numberOfRows )
             break; 
     }
     fileAccess.close();
     long endTime = System.currentTimeMillis();
     long actualTimeTaken = endTime - startTime;
     System.out.println( String.format("No Of Rows %s , Time(sec) %s ", numberOfRows, actualTimeTaken / 1000f) ) ;  
 }

有关问题的任何提示?

编辑1:异常问题已解决并按如下方式解答。

编辑2:关于表现的最佳选择。

@EJP:这是使用围绕BufferedOutputStream的DataOutputStream的代码。

static void writeFileDataBuffered() throws IOException{
        File file = File.createTempFile("dbf", ".txt", new File("C:\\Output"));
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream( file )));
        long counter = 1;
        long million = 1000000;
        long numberOfRows = million * 100;
        long startTime = System.currentTimeMillis();
        while(true){
            out.writeBytes( counter + System.lineSeparator() );
            counter++;
            if ( counter > numberOfRows )
                break;
        }
        out.close();
        long endTime = System.currentTimeMillis();
        System.out.println("Number of Rows: "+ numberOfRows + ", Time(sec): " + (endTime - startTime)/1000f);
    }

.......... 感谢

1 个答案:

答案 0 :(得分:0)

经过一些背景工作,我找到了根本原因。我声明的bufferSize小于我写的内容长度。

1亿条记录所需的字节数为:988888898,而带有(long)的缓冲区大小(Math.pow(10240,2))为:104857600.bufferSize缩短884031298字节。如异常所示,这导致了问题。

bufferSize也可以用作Integer.MAX_VALUE,而不是计算正在写入的内容大小。虽然这会增加文件大小,但根据我的试运行结果,它对程序的性能没有任何影响。

.........

由于