java nio文件映射问题,求助

nyzlhao 2009-04-29 12:33:56

RandomAccessFile raf = new RandomAccessFile(file, "r");

FileChannel channel = raf.getChannel();
int size = (int) channel.size();
MappedByteBuffer inbuff = channel.map(FileChannel.MapMode.READ_ONLY, 0,size);//当这里的size比较大的时候报java.lang.OutOfMemoryError: Map failed
/*
下面就是拿到inbuff向文件里面写
*/


怎么实现文件的某一部分射到内存中,下一次再继续映射,麻烦给个例子
...全文
362 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
nyzlhao 2009-05-04
  • 打赏
  • 举报
回复
非常谢谢你细心的回答,谢谢!!!
jinxfei 2009-04-30
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 nyzlhao 的回复:]
我用了你上面,但是文件读出来是不能用的,像视频就播放不了
[/Quote]

是你原来自己的代码就有问题:

我又改了一下:

/**
*
* @param file:这个方法是为了解决传入一个
*/
public void accessFileTest(File file) {
InetAddress toIp;
RandomAccessFile raf = null;
FileChannel channel = null;

FileChannel chx = null;
RandomAccessFile put = null;

MappedByteBuffer mabuff = null;
try {
// toIp = InetAddress.getByName("127.0.0.1");
// Socket client = new Socket(toIp, 6789);
// ByteBuffer buff = ByteBuffer.allocate(8196);
// //1:得到写的流
// OutputStream os = client.getOutputStream();
// //2:制作输出流
raf = new RandomAccessFile(file, "r");

channel = raf.getChannel();


/*for(int i=0;i<size;i++){
int c = buff.get;
os.write(c);
}*/



put = new RandomAccessFile(new File("f:\\test_new.rmvb"), "rw");
chx = put.getChannel();
//int s = (int)chx.size();
//MappedByteBuffer putbuff = chx.map(FileChannel.MapMode.READ_WRITE, 0, size);

long l1 = System.currentTimeMillis();
long position = 0;
long size=1024*1024*50;//每次10M,不要太小,否则没有意义
mabuff = channel.map(FileChannel.MapMode.READ_ONLY, 0,size);//这里的size设置成其他的就报错,放成上面的size,在文件小于280M时都可以传,但是很大就不可以了,报错,大家可以试
long fileLen=raf.length();
while (channel.position()<fileLen) //for(int i = 0;i<size;i++)
{
//System.out.println(mabuff.get());

chx.write(mabuff);
position = position+size;
//System.out.println(i);
//mabuff.clear();都试过了不好使
//mabuff.force();
if ((fileLen-position)<size){
size=fileLen-position;
}
if (size==0){
break;
}
System.out.println(raf.length()+":"+channel.position()+":"+size);
mabuff = channel.map(FileChannel.MapMode.READ_ONLY, position, size);
System.gc();
}
long total = System.currentTimeMillis() - l1;
System.out.println("所用时间" + total);
InputStream in=this.getClass().getResourceAsStream("");
//3:把输出流写出去,
//os.write(buf);
//os.flush();



} catch (Exception ex) {

ex.printStackTrace();
} finally {
try {
channel.close();
raf.close();

chx.close();
put.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}


}
nyzlhao 2009-04-30
  • 打赏
  • 举报
回复
我用了你上面,但是文件读出来是不能用的,像视频就播放不了
GeekZFZ 2009-04-29
  • 打赏
  • 举报
回复
帮顶一下
jinxfei 2009-04-29
  • 打赏
  • 举报
回复
我有测试了一下,这个SIZE设置的太小不行,效率太低,我直接设置10M,每个循环调用GC来回收内存,还是挺快的,
而且也复制了1.7G的一个文件:


size=1024*1024*10;//每次10M,不要太小,否则没有意义
mabuff = channel.map(FileChannel.MapMode.READ_WRITE, 0,size);//这里的size设置成其他的就报错,放成上面的size,在文件小于280M时都可以传,但是很大就不可以了,报错,大家可以试

while (mabuff.hasRemaining()) //for(int i = 0;i<size;i++)
{
//System.out.println(mabuff.get());

chx.write(mabuff);
position = position + size;
//System.out.println(i);
//mabuff.clear();都试过了不好使
//mabuff.force();

mabuff = channel.map(FileChannel.MapMode.READ_WRITE, position, size);
System.gc(); }
jinxfei 2009-04-29
  • 打赏
  • 举报
回复
这是java1.4.2就有的一个bug,官方网站上有:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5095540

不过,sun似乎并没有解决这个问题,直接close并定义为不可重现:
Bug ID: 5095540
Votes 30
Synopsis JVM crash with outOfMemoryError in growableArray.cpp error
Category hotspot:runtime_system
Reported Against 1.4.2_05
Release Fixed
State 11-Closed, Not Reproducible, bug
Priority: 2-High
Related Bugs
Submit Date 01-SEP-2004


--------------
而java doc对map方法的说明也指出:

For most operating systems, mapping a file into memory is more expensive than reading or writing a few tens of kilobytes of data via the usual read and write methods. From the standpoint of performance it is generally only worth mapping relatively large files into memory.


也就是说,对大部分操作系统而言,将文件映射到内存,比直接使用read方法读出几十KB要慢得多(expensive)。
nyzlhao 2009-04-29
  • 打赏
  • 举报
回复
我把代码附上,做过的帮个忙,谢谢了

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ny;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
*
* @author wangjing
*/
public class FileTransferClient {

/**
* 文件的读取用到两个类,第一个是RandomAccessFile用来支持断点续传,第二个是FileChannel是将文件映射到内存中来读取
*/
public FileTransferClient() {/*
InetAddress toIp;
byte buf[];
try {
toIp = InetAddress.getByName("127.0.0.1");
Socket client = new Socket(toIp, 6789);
//1:得到写的流
OutputStream os = client.getOutputStream();
//2:制作输出流
buf = "王靖".getBytes();
//3:把输出流写出去,
os.write(buf);
os.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
*/

}

/**
*
* @param file:这个方法是为了解决传入一个
*/
public void accessFileTest(File file) {
InetAddress toIp;
RandomAccessFile raf = null;
FileChannel channel = null;

FileChannel chx = null;
RandomAccessFile put = null;

MappedByteBuffer mabuff = null;
try {
// toIp = InetAddress.getByName("127.0.0.1");
// Socket client = new Socket(toIp, 6789);
// ByteBuffer buff = ByteBuffer.allocate(8196);
// //1:得到写的流
// OutputStream os = client.getOutputStream();
// //2:制作输出流
raf = new RandomAccessFile(file, "rw");

channel = raf.getChannel();
int size = (int) channel.size();

/*for(int i=0;i<size;i++){
int c = buff.get;
os.write(c);
}*/



put = new RandomAccessFile(new File("f:\\test.rmvb"), "rw");
chx = put.getChannel();
//int s = (int)chx.size();
//MappedByteBuffer putbuff = chx.map(FileChannel.MapMode.READ_WRITE, 0, size);

long l1 = System.currentTimeMillis();
int position = 0;

mabuff = channel.map(FileChannel.MapMode.READ_WRITE, 0,9612);//这里的size设置成其他的就报错,放成上面的size,在文件小于280M时都可以传,但是很大就不可以了,报错,大家可以试

while (mabuff.hasRemaining()) //for(int i = 0;i<size;i++)
{
//System.out.println(mabuff.get());

chx.write(mabuff);
position = position + 9612;
//System.out.println(i);
//mabuff.clear();都试过了不好使
//mabuff.force();
mabuff = channel.map(FileChannel.MapMode.READ_WRITE, position, 9612);
}
long total = System.currentTimeMillis() - l1;
System.out.println("所用时间" + total);
//3:把输出流写出去,
//os.write(buf);
//os.flush();



} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
channel.close();
raf.close();

chx.close();
put.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}


}

public static void main(String[] args) {
FileTransferClient fc = new FileTransferClient();
fc.accessFileTest(new File("e:\\media\\非常人贩2(中英字幕).rmvb"));
}
}



像上面的代码来运行就报
# java.lang.OutOfMemoryError: requested 64000 bytes for GrET in C:\BUILD_AREA\jdk6_06\hotspot\src\share\vm\utilities\growableArray.cpp. Out of swap space?
asdtiang 2009-04-29
  • 打赏
  • 举报
回复
seek
public void seek(long pos)
throws IOException设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。偏移量的设置可能会超出文件末尾。偏移量的设置超出文件末尾不会改变文件的长度。只有在偏移量的设置超出文件末尾的情况下对文件进行写入才会更改其长度。

参数:
pos - 从文件开头以字节为单位测量的偏移量位置,在该位置设置文件指针。
抛出:
IOException - 如果 pos 小于 0 或者发生 I/O 错误。
ET郭强 2009-04-29
  • 打赏
  • 举报
回复
学习下,
jxst051665 2009-04-29
  • 打赏
  • 举报
回复
thinking in java 4th edition
I/O那一章里有关于nio的,我估计你看过了
jxst051665 2009-04-29
  • 打赏
  • 举报
回复
本来想说 去看 thinking in java 4th edition
看到楼主的技术分,估计帮不上忙了。。。

帮顶
悠云guo 2009-04-29
  • 打赏
  • 举报
回复
既然是某一部分,那你为啥还要直接取size?
取你需要的大小就是了

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧