iteye_13980
2011-06-07 15:40 阅读 725
已采纳

用MappedByteBuffer写大文件

在search了很多的有关文章,没有找到用MappedByteBuffer写大文件的具体例子.
大部分都是代码类似于:
[code="java"]
MappedByteBuffer raf = fc.map(MapMode.READ_WRITE, 0, fc.size());
[/code]
或是
MappedByteBuffer raf = fc.map(MapMode.READ_WRITE, 0, someHardCode);

[b]需求是这样的: 文件开始并不存在, 并且文件最后到底是多大我也不清楚.[/b]

我的代码如下:

[code]
public static void test2() throws Exception {
//先将上次文件删除
new File("D:/test2.tmp").delete();
RandomAccessFile raf1 = new RandomAccessFile("D:/test2.tmp","rw");
int mapsize = 1024*100;//100K
FileChannel fc = raf1.getChannel();
MappedByteBuffer raf = fc.map(MapMode.READ_WRITE, 0, mapsize);

    byte[] b1 = new byte[]{'a','b','c','d','e','f','g','h'};
    byte[] utfstr = "this is a test".getBytes("UTF-8");

    long s1 = System.currentTimeMillis();
    for(int i=0;i<10000000;i++){//写一千万次, 

//在循环内部, 会发生 java.nio.BufferOverflowException 异常 !!!!!!
raf.put(b1);
raf.putInt(i);
raf.putInt(i+1);

        raf.put(utfstr);
        raf.put((byte)'\n');
    }
    long d1 = System.currentTimeMillis() - s1;
    fc.close();
    raf1.close();
    System.out.println("spent time1="+(d1/1000));
}

[/code]

望有同学指定一下: 是否 MappedByteBuffer 并不适合这种 不断地 append 的写入方式, 只适合大小已经固定的文件的原来内容的改写?

如果也适合的话, 麻烦请个示例代码! 谢谢!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

5条回答 默认 最新

  • 已采纳
    weixin_42560972 也许世界还没停 2011-06-08 21:19

    [code="java"] long cout = 0;

    for (int i = 0; i < 100000; i++) {// 写一千万次,

    // 在循环内部, 会发生 java.nio.BufferOverflowException 异常 !!!!!!

    if (raf.remaining() < 1024) {

    cout += raf.position();

    raf = fc.map(MapMode.READ_WRITE, cout, mapsize);

        }  
        raf.put(b1);  
    
        raf.put(utfstr);  
        raf.put((byte) '\n');  
    }  [/code]
    

    注意map超过文件的长度,会使得文件变大

    点赞 评论 复制链接分享
  • weixin_42560972 也许世界还没停 2011-06-07 17:21

    [code="java"] int mapsize = 1024*100;//100K

    FileChannel fc = raf1.getChannel();

    MappedByteBuffer raf = fc.map(MapMode.READ_WRITE, 0, mapsize); [/code]

    这里是否是只映射了100k?
    写数据超过100k了吧

    MappedByteBuffer是为了不一次将大文件载入内存,而只映射其中的一部分。
    当数据超过了原映射大小时,可以向后偏移映射应该可以,但是需要计算已经写入的字节数

    点赞 评论 复制链接分享
  • weixin_42560972 也许世界还没停 2011-06-07 17:27

    如果需要一直在文件尾部添加数据,可以如下:
    [code="java"] File file = new File("1.tmp");
    FileOutputStream fos = new FileOutputStream(file, true);
    ObjectOutputStream ois = new ObjectOutputStream(fos);
    byte[] b1 = new byte[]{'a','b','c','d','e','f','g','h'};

    byte[] utfstr = "this is a test".getBytes("UTF-8");

        for (int i = 0; i < 10000000; i++) {// 写一千万次,
            ois.write(b1);
            ois.writeInt(i);
            ois.writeInt(i + 1);
    
            ois.write(utfstr);
            ois.write((byte) '\n');
        }[/code]
    
    点赞 评论 复制链接分享
  • weixin_42560972 也许世界还没停 2011-06-07 19:41

    [code="java"] for (int i = 0; i < loop; i++) {// 写一千万次,
    if (raf.remaining() < 1024) {
    raf = fc.map(MapMode.READ_WRITE, raf.position(), mapsize);
    }
    raf.put(b1);
    raf.putInt(i);
    raf.putInt(i + 1);

            raf.put(utfstr);
            raf.put((byte) '\n');
        }[/code]
    

    不知道有没有更好的办法

    点赞 评论 复制链接分享
  • weixin_42560972 也许世界还没停 2011-06-08 09:19

    [code="java"] if (raf.remaining() < 1024) {
    mapsize += mapsize;
    raf = fc.map(MapMode.READ_WRITE, raf.position(), mapsize);
    }[/code]

    点赞 评论 复制链接分享

相关推荐