用bytejava 读取文件到byte,怎么判断文件读取结束

用java如何读取一个文件的指定字节位置的数据?_百度知道
用java如何读取一个文件的指定字节位置的数据?
可以使用RandomAccessFile类。例如要从100字节开始输出工作目录下的data.txt文件的类容。package konw.test1;import java.io.FileNotFoundEimport java.io.IOEimport java.io.RandomAccessFpublic class Test1{
public static void main(String[] args)
long pos = 100;
String str = &&;
RandomAccessFile randomAccessFile = new RandomAccessFile(&data.txt&, &rw&);
randomAccessFile.seek(pos);//将文件流的位置移动到pos字节处
while( (str = randomAccessFile.readLine()) != null)
System.out.println(str);
randomAccessFile.close();
} catch (FileNotFoundException e)
e.printStackTrace();
} catch (IOException e)
e.printStackTrace();
其他类似问题
为您推荐:
提问者采纳
byte[] buff=new byte[4];
DataInputStream dis=new DataInputStream(new FileInputStream(new File(&c:/rr.ifo&)));
dis.skip(32);
dis.read(buff);
ByteArrayInputStream bintput = new ByteArrayInputStream(buff);
int f = bintput.read();
System.out.println(f); } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
提问者评价
谢谢,和上面的相反,这只能读Little字节序的文件
其他2条回答
public static void testReadFile(){ RandomAccessFile raf = try {
raf = new RandomAccessFile(&c:/out.txt&, &r&);
//跳字节数
raf.skipBytes(32);
//读取数字
int num = raf.readInt();
System.out.println(num);
raf.close(); } catch (Exception e) {
e.printStackTrace(); }}
佩服的耳力
java的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁117.42.239.*
哥你有这勇力我佩服你呀,说得头头是道呀
您的举报已经提交成功,我们将尽快处理,谢谢!
“卡门”有很多选曲,这里有三只。
大家还关注
(window.slotbydup=window.slotbydup || []).push({
id: '2081942',
container: s,
size: '1000,60',
display: 'inlay-fix'用心创造滤镜
扫码下载App
汇聚2000万达人的兴趣社区下载即送20张免费照片冲印
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
河北保定人
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
在传输数据的过程中,我们需要判断流中传输的数据何时结束这样的问题。这对于我们正确地发送和接收数据是非常关键的。如何判断流的末尾和批数据的末尾,是解决这个问题的关键。本文就是要深入地分析Java I/O输入输出的工作原理,保证我们能够正确地执行数据的发送和接收!Java I/O任务一个Java的I/O任务,创建了一个连接两个系统的数据传输管道。它分为两个部分:输入流和输出流。输入流,指的是通过流向本系统的内存传输数据的单向数据传输通道。输出流,指的是通过流向外部系统传输数据的单向数据传输通道。&输入流&InputStream类是表示字节输入流的所有类的超类。这是一个抽象类。我们看它提供的读入数据的方法:readpublic abstract int read()&&&&&&&&&&&&&&&&& throws 从输入流读取下一个数据字节。返回&0&到&255&范围内的&int&字节值。如果因已到达流末尾而没有可用的字节,则返回值&-1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。子类必须提供此方法的一个实现。返回:下一个数据字节,如果到达流的末尾,则返回&-1。抛出:&- 如果发生 I/O 错误。readpublic int read(byte[]&b)&&&&&&&& throws 从输入流中读取一定数量的字节并将其存储在缓冲区数组&b&中。以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。如果&b&为&null,将抛出&NullPointerException。如果&b&的长度为 0,则无字节可读且返回&0;否则,要尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值&-1;否则,至少可以读取一个字节并将其存储在&b&中。将读取的第一个字节存储在元素&b[0]&中,下一个存储在&b[1]&中,依次类推。读取的字节数最多等于&b&的长度。让&k&为实际读取的字节数;这些字节将存储在元素&b[0]&至b[k-1]&之间,不影响元素&b[k]&至&b[b.length-1]。如果不是因为流位于文件末尾而无法读取读取第一个字节,则抛出&IOException。特别是,如果输入流已关闭,则抛出&IOException。类&InputStream&的&read(b)&方法的效果等同于:&read(b, 0, b.length) 参数:b&- 读入数据的缓冲区。返回:读入缓冲区的总字节数,如果由于流末尾已到达而不再有数据,则返回&-1。抛出:&- 如果发生 I/O 错误。&- 如果&b&为&null。另请参见:readpublic int read(byte[]&b,&&&&&&&&&&&&&&& int&off,&&&&&&&&&&&&&&& int&len)&&&&&&&& throws 将输入流中最多&len&个数据字节读入字节数组。尝试读取多达&len&字节,但可能读取较少数量。以整数形式返回实际读取的字节数。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。如果&b&为&null,则抛出&NullPointerException。如果&off&为负,或&len&为负,或&off+len&大于数组&b&的长度,则抛出IndexOutOfBoundsException。如果&len&为 0,则没有字节可读且返回&0;否则,要尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值&-1;否则,至少可以读取一个字节并将其存储在&b&中。将读取的第一个字节存储在元素&b[off]&中,下一个存储在&b[off+1]&中,依次类推。读取的字节数最多等于&len。让&k&为实际读取的字节数;这些字节将存储在元素b[off]&至&b[off+k-1]&之间,其余元素&b[off+k]&至&b[off+len-1]&不受影响。在任何情况下,元素&b[0]&至&b[off]&和元素&b[off+len]&至&b[b.length-1]&都不会受到影响。如果不是因为流位于文件末尾而无法读取第一个字节,则抛出&IOException。特别是,如果输入流已关闭,则抛出&IOException。类&InputStream&的&read(b,&off,&len)&方法只重复调用方法&read()。如果第一个这样的调用导致&IOException,则从对&read(b,&off,&len)&方法的调用中返回该异常。如果对&read()&的任何后续调用导致&IOException,则该异常会被捕获并将发生异常时的位置视为文件的末尾;到达该点时读取的字节存储在&b&中并返回发生异常之前读取的字节数。建议让子类提供此方法的更有效的实现。参数:b&- 读入数据的缓冲区。off&- 在其处写入数据的数组&b&的初始偏移量。len&- 要读取的最大字节数。返回:读入缓冲区的总字节数,如果由于已到达流末尾而不再有数据,则返回&-1。抛出:&- 如果发生 I/O 错误。&- 如果&b&为&null。另请参见:&&read方法解读这些方法的核心。实际上就是read()方法。这个方法的JavaDoc中指出:“如果因已到达流末尾而没有可用的字节,则返回值&-1。如果因已到达流末尾而没有可用的字节,则返回值&-1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。”&1,read方法会在能够返回流中的字节之前,一直阻塞线程。这就是说,read方法是一个低消耗的监听和读取I/O传输的好方法。这个方法的实现,具有非常高的性能。&2,如果输入流的I/O系统在执行这个read方法时抛出异常,那么显然这个方法会非正常结束,这个也是毫无疑问的。&3,“如果因已到达流末尾而没有可用的字节,则返回值&-1。”这句话看似没有问题,但实际上有非常大的歧义!什么是流的末尾?只有流的末尾才能返回-1吗?&InputStream类和SocketInputStream类的源码解读通过查看InputStream类的源码,我发现实际上,流,就好比是双向2车道的高速公路。它传输数据是一批一批的。我把它叫做“批数据”。假设A=======B两个系统通过一个I/O流来连接。那么,从B端通向A端的车道,就叫作A的“输入流”。同一条车道,在B这边,叫作B的“输出流”。同理,从A端通向B端的车道,就叫作A的“输出流”。同一条车道,在B这边,就叫作B的“输入流”。&数据在这条高速公路上,不是一条一条跑的,而是一批一批跑。&OutputStream类,此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。 &OutputStream类的write方法,每执行一次,就向这条高速公路上发送了一批数据。OutputStream类的一些子类,它们并不是在每次write()方法执行之后立刻把这批数据发送到数据高速公路上的。而是只有在执行flush()方法之后,才把之前write的多批数据真正地发送到数据通道中。这样,多个write()方法发送的数据就变为了一批数据了!&通过read()方法读入时,当读完该批数据之后,如果再一次执行read()方法,就会立刻返回-1。实际上,这是并没有到达流的末尾!仅仅是读完了一批发送的数据而已!&如果我们又一次执行read()方法,那么,如果:1,流没有结束。也就是说,对面的发送端可能还会发送下一批数据时,就会进入阻塞状态。当前线程暂停,直到读取到输入流中下一批数据的第一个字节。2,流结束了。也就是说,对面的发送端不再发送任何数据,也即:这条数据通道已经没有用了,这时,可以说“到达流的末尾”了!返回-1。&&& 所以,InputStream及其子类的read()方法的注释是不完整的!Read()方法的注释,应该这么说:readpublic abstract int read()&&&&&&&&&&&&&&&&& throws 从输入流读取下一个数据字节。返回&0&到&255&范围内的&int&字节值。如果在读完一批数据后首次调用read()方法,那么返回-1。表示这批数据已经读完了!如果因已到达流末尾而没有可用的字节,则返回值&-1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。子类必须提供此方法的一个实现。返回:下一个数据字节;如果刚读完一批数据,则返回-1;如果到达流的末尾,则返回&-1。抛出:&- 如果发生 I/O 错误。&&如何正确使用Java I/O输出和读入数据明白了Java的I/O流的工作机理和read方法的执行结果,我们就能够正确地使用Java I/O系统输出和读入数据了。&如何分批输出数据由于read(…)方法是分批读取数据的,所以,我们应该在输出端正确地分批输出数据。Write(…)方法,然后执行flush()方法能够将多批数据合并成一批数据输出。尽管OutputStream这个基类的flush()方法是无用的,但是由于我们得到的OutputStream类型的输出对象都是这个类的子类的对象,所以,我们还是应该尽量使用flush()方法强制向输出流中物理输出数据,以避免错误。&如何分批读取数据&&& 我们常常使用public int read(byte[]&b,&&&&&&&&&&&&&&& int&off,&&&&&&&&&&&&&&& int&len)&&&&&&&& throws&这个方法来读取一批数据。查看这个方法的源代码,我们可以发现,它在读取完一批数据时,又执行了一次read()方法,由于前面论述的原因,这个方法立刻返回-1,然后这个方法退出,返回这次读取的字节数。因此,如果我们要读取一批数据,可以采用如下几种方法:使用read()判断-1来读完一批数据:&&&&代码示例:IWhile((byte=inputStream.read())!=-1 ){&&& Byte就是返回的字节。&}如果读完一批数据后再一次执行read方法,将会立刻返回-1,表示这批数据已经读完。&使用read(byte[] buffer)判断是否返回小于buffer.length或者-1来判断是否读完一批数据上面那样一个一个字节读取数据比较麻烦,我们通常使用一个字节数组来读取数据。read(byte[] buffer)方法返回:1,buffer.length,表示从输入流中读取到的数据塞满了这个字节数组。此时,可能已经读完了这批数据,也可能没有读完这批数据。&&&&如果刚好读完,那么再执行一次read()方法,就会返回-1,表示这批数据已经读完,而不是表示流已经结束。2,小于buffer.length。表示读完了该批数据。并且执行了一次read()方法,返回-1,表示这批数据已经读完。3,-1。这批数据已经读完了。&不可能是表示流已经结束。因为之前就会退出while循环。&&&代码示例:Byte[] buffer=new byte[1024];int size=buffer.While(size!=-1 || size&=buffer.length){Size=inputStream.read(buffer));将数据读到数组buffer中。如果读到了-1,或者 读出的数据少于buffer的尺寸,表示已经读完该批数据,不再循环读取数据了!&&}&&读入一批数据的操作必须对应输出一批数据的操作读入一批数据的操作必须对应输出一批数据的操作。否则,读入数据的线程会一直阻塞,等待输出端输出下一批数据。如果对方也需要我们提供输出数据,那么就可能会使整个流的两端的线程互相等待,死锁住。并且这个I/O流也会永远不释放,这样就会使系统的资源耗尽。
阅读(2638)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'android 文件读写(inputStream)',
blogAbstract:'Java的I/O系统使用“流”来处理各种类型的输入、输出数据的任务。在传输数据的过程中,我们需要判断流中传输的数据何时结束这样的问题。这对于我们正确地发送和接收数据是非常关键的。',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:7,
publishTime:2,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'河北保定人',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}java 读取txt文件 想自定义从第几个字节开始读和读几个字节 怎么做??
java 读取txt文件 想自定义从第几个字节开始读和读几个字节 怎么做?? 20
用java读取txt文件,由于要用一个txt文件记录很多信息,所以读取时候需要选择从哪个字节开始读取,这个应该怎么写。。。另外要是能设定读取几个字节的内容更好。。或者有其他办法也可以~~
例如:txt文件内容:
a.asp&& C:\& &aaa
b.jsp&& D:\&& bbb
怎么分别读出这两种内容(前两行,后两行)。。多谢。。
1.想自定义从第几个字节开始读使用java.io.RandomAccessFile类,可使用构造方法RandomAccessFile af=new RandomAccessFile("C:\\1.txt","r");
如果想从第100个字节开始读,可使用其方法:public void seek(long&pos),如af.seek(100);
2.读几个字节
所有的输入流都有方法:public int read(byte[]&b,&&&&&&&&&&&&&&& int&off,&&&&&&&&&&&&&&& int&len)假如你想一次读20个字节,可使用:
byte b[] = new byte[100];
input.read(b,0,20);
然后使用String str = new String(b,0,20);得到你读取的内容
的感言:多谢。。也感谢其他朋友。 满意答案
在读取的时候用skip()跳过多少个字符,然后再开始读~~~~~~~
谢谢回复~~那skip()具体应该怎么用呢。。假如我用BufferedReader
BufferedReader(new
FileReader("./b.txt"));s=in.readLine();StringTokenizer
StringTokenizer(s);这样来读。。怎样读上面说的第三、四行信息??
import java.io.BufferedRimport java.io.FileRimport java.io.IOE
public class ByteToInt {&public static void main(String[]args)&{&&try{&&BufferedReader in=new BufferedReader(new FileReader("f:/b.txt"));
&&String s=in.readLine();&&int position=0;&&while(null!=s)&&{&&&if(position&2)&&&&in.skip(s.length());&&&else&&&&System.out.println(s);&&&s=in.readLine();&&&position++;&&}&&}catch(IOException ex)&&{&&&&&}
的感言:多谢。。基本解决! 相关知识
其他回答 (3)
Reader是字符流,你要读字节就是InputStream,JAVA不像.NET,没有直接读行的方法,只有自己判断,读到回车就行数+1。回车用 \n或者 0x0a 判断
import java.io.BufferedRimport java.io.FileRimport java.io.FileW/**&*删除文件每行的前3个字&* @author airing&*/public class Main {&&& public static void main(String[] args) {&&&&&&& String path = "D:/a.txt";&&&&&&& String path1 = "D:/b.txt";&&&&&&& int number=0;&&&&&&& Main main=new Main();&&&&&&& main.cutForward(path,path1,number);&&& }/**&* 删除文件每行的前3个字&*/&&& public void cutForward(String path,String path1,int number) {&&&&&&& &&&&&&& try {&&&&&&&&&&& FileReader fr = new FileReader(path);&&&&&&&&&&& BufferedReader br = new BufferedReader(fr);&&&&&&&&&&& String line = br.readLine();&&&&&&&&&&& FileWriter fw = new FileWriter(path1);&&&&&&&&&&& while (line != null) {&&&&&&&&&&&&&&& line=line.substring(number, line.length());&&&&&&&&&&&&&&& fw.write(line + "\n");&&&&&&&&&&&&&&& line = br.readLine();&&&&&&&&&&& }&&&&&&&&&&& fw.close();&&&&&&&&&&& br.close();&&&&&&&&&&& fr.close();&&&&&&& } catch (Exception e) {&&&&&&&&&&& e.printStackTrace();&&&&&&& }&&& }}
String path = "文件路径";
InputStream is = new FileInputStream(path);BufferedReader reader = new BufferedReader(&&&&&new InputStreamReader(is));
String str = reader.readLine();while (str != null) {
&&&&&&& //在这个地方就是每一行的数据。自己看怎么控制一下读那行就行了
&&&&&&& //str& 就是每一行的数据
&&& } catch (Exception e) {&&&&&&& System.out.println(e.toString());
&&&&} finally {&&&&&str = reader.readLine();&&&&}
相关知识等待您来回答
编程领域专家
& &SOGOU - 京ICP证050897号java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射 - 正走向大牛的菜鸟 - ITeye技术网站
博客分类:
java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果文件超大的话,更快的方式是采用。
是java nio引入的文件内存映射方案,读写性能极高。NIO最主要的就是实现了对异步操作的支持。其中一种通过把一个套接字通道(SocketChannel)注册到一个选择器(Selector)中,不时调用后者的选择(select)方法就能返回满足的选择键(SelectionKey),键中包含了SOCKET事件信息。这就是select模型。
SocketChannel的读写是通过一个类叫ByteBuffer(java.nio.ByteBuffer)来操作的.这个类本身的设计是不错的,比直接操作byte[]方便多了. ByteBuffer有两种模式:直接/间接.间接模式最典型(也只有这么一种)的就是HeapByteBuffer,即操作堆内存 (byte[]).但是内存毕竟有限,如果我要发送一个1G的文件怎么办?不可能真的去分配1G的内存.这时就必须使用"直接"模式,即 MappedByteBuffer,文件映射.
先中断一下,谈谈操作系统的内存管理.一般操作系统的内存分两部分:物理内存;虚拟内存.虚拟内存一般使用的是页面映像文件,即硬盘中的某个(某些)特殊的文件.操作系统负责页面文件内容的读写,这个过程叫"页面中断/切换". MappedByteBuffer也是类似的,你可以把整个文件(不管文件有多大)看成是一个ByteBuffer.MappedByteBuffer 只是一种特殊的 ByteBuffer ,即是ByteBuffer的子类。 MappedByteBuffer 将文件直接映射到内存(这里的内存指的是虚拟内存,并不是物理内存)。通常,可以映射整个文件,如果文件比较大的话可以分段进行映射,只要指定文件的那个部分就可以。三种方式:
FileChannel提供了map方法来把文件影射为内存映像文件: MappedByteBuffer map(int mode,long position,long size); 可以把文件的从position开始的size大小的区域映射为内存映像文件,mode指出了 可访问该内存映像文件的方式:READ_ONLY,READ_WRITE,PRIVATE.
a. READ_ONLY,(只读): 试图修改得到的缓冲区将导致抛出 ReadOnlyBufferException.(MapMode.READ_ONLY) b. READ_WRITE(读/写): 对得到的缓冲区的更改最终将传播到文件;该更改对映射到同一文件的其他程序不一定是可见的。 (MapMode.READ_WRITE)c. PRIVATE(专用): 对得到的缓冲区的更改不会传播到文件,并且该更改对映射到同一文件的其他程序也不是可见的;相反,会创建缓冲区已修改部分的专用副本。 (MapMode.PRIVATE)三个方法:a. fore();缓冲区是READ_WRITE模式下,此方法对缓冲区内容的修改强行写入文件b. load()将缓冲区的内容载入内存,并返回该缓冲区的引用c. isLoaded()如果缓冲区的内容在物理内存中,则返回真,否则返回假三个特性:
调用信道的map()方法后,即可将文件的某一部分或全部映射到内存中,映射内存缓冲区是个直接缓冲区,继承自ByteBuffer,但相对于ByteBuffer,它有更多的优点:a. 读取快b. 写入快c. 随时随地写入下面来看代码:
import java.io.FileInputS
import java.io.FileOutputS
import java.nio.ByteB
import java.nio.MappedByteB
import java.nio.channels.FileC
public class MapMemeryBuffer {
public static void main(String[] args) throws Exception {
ByteBuffer byteBuf = ByteBuffer.allocate(1024 * 14 * 1024);
byte[] bbb = new byte[14 * 1024 * 1024];
FileInputStream fis = new FileInputStream("e://data/other/UltraEdit_17.00.0.1035_SC.exe");
FileOutputStream fos = new FileOutputStream("e://data/other/outFile.txt");
FileChannel fc = fis.getChannel();
long timeStar = System.currentTimeMillis();
fc.read(byteBuf);
System.out.println(fc.size()/1024);
long timeEnd = System.currentTimeMillis();
System.out.println("Read time :" + (timeEnd - timeStar) + "ms");
timeStar = System.currentTimeMillis();
fos.write(bbb);
timeEnd = System.currentTimeMillis();
System.out.println("Write time :" + (timeEnd - timeStar) + "ms");
fos.flush();
fc.close();
fis.close();
运行结果:
Read time :24ms
Write time :21ms
我们把标注1和2语句注释掉,换成它们下面的被注释的那条语句,再来看运行效果。14235
Read time :2ms
Write time :0ms
可以看出速度有了很大的提升。MappedByteBuffer的确快,但也存在一些问题,主要就是内存占用和文件关闭等不确定问题。被MappedByteBuffer打开的文件只有在垃圾收集时才会被关闭,而这个点是不确定的。在javadoc里是这么说的:A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself
is garbage-collected.这里提供一种解决方案:
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
getCleanerMethod.setAccessible(true);
sun.misc.Cleaner cleaner = (sun.misc.Cleaner)
getCleanerMethod.invoke(byteBuffer, new Object[0]);
cleaner.clean();
} catch (Exception e) {
e.printStackTrace();
return null;
关于MappedByteBuffer资源释放问题
JDK1.4中加入了一个新的包:NIO(java.nio.*)。这个库最大的功能(我认为)就是增加了对异步套接字的支持。其实在 其他语言中,包括在最原始的SOCKET实现(BSD SOCKET),这是一个早有的功能:异步回调读/写事件,通过选择器动态选择感兴趣的事件,等等。
先谈谈操作系统的内存管理。一般操作系统的内存分两部分:物理内存;虚拟内存。虚拟内存一般使用的是页面映像文件,即硬盘中的某个(某些)特殊的文件.操作系统负责页面文件内容的读写,这个过程叫"页面中断/切换"。
MappedByteBuffer也是类似的,你可以把整个文件(不管文件有多大)看成是一个ByteBuffer。这是一个很好的设计,除了令人头疼的一点在后面会讲到。
java.nio.MappedByteBuffer
MappedByteBuffer是一个比较方便使用的类。其内容是文件的内存映射区域。映射的字节缓冲区是通过 方法创建的。映射的字节缓冲区和它所表示的文件映射关系在该缓冲区本身成为垃圾回收缓冲区之前一直保持有效。此类用特定于内存映射文件区域的操作扩展
类。 这个类本身的设计是不错的,比直接操作byte[]方便多了。
ByteBuffer有两种模式:直接/间接。间接模式最典型(也只有这么一种)的就是HeapByteBuffer,即操作堆内存(byte [])。但是内存毕竟有限,如果我要发送一个1G的文件怎么办?不可能真的去分配1G的内存.这时就必须使用"直接"模式,即 MappedByteBuffer,文件映射。
在JDK API文档中这样描述的:
全部或部分映射的字节缓冲区可能随时成为不可访问的,例如,如果我们截取映射的文件。试图访问映射的字节缓冲区的不可访问区域将不会更改缓冲区 的内容,并导致在访问时或访问后的某个时刻抛出未指定的异常。因此强烈推荐采取适当的预防措施,以避免此程序或另一个同时运行的程序对映射的文件执行操作 (读写文件内容除外)。
MappedByteBuffer只能通过调用FileChannel的map()取得,再没有其他方式.但是令人奇怪的是,SUN提供了map()却没有提供unmap().这样会导致什么后果呢?
这样,问题就出现了。通过MappedByteBuffer实现文件复制功能非常容易,可以用以下方法来实现。
//文件复制
public void copyFile(String filename,String srcpath,String destpath)throws IOException {
File source = new File(srcpath+"/"+filename);
File dest = new File(destpath+"/"+filename);
FileChannel in = null, out =
in = new FileInputStream(source).getChannel();
out = new FileOutputStream(dest).getChannel();
long size = in.size();
MappedByteBuffer buf = in.map(FileChannel.MapMode.READ_ONLY, 0, size);
out.write(buf);
in.close();
out.close();
source.delete();//文件复制完成后,删除源文件
}catch(Exception e){
e.printStackTrace();
} finally {
in.close();
out.close();
但是如果要实现文件文件复制完成后,删除源文件,以上方法就有问题。因为在source.delete()时,会返回false,删除失败,主 要原因是变量buf仍然有源文件的句柄,文件处于不可删除状态。既然MappedByteBuffer是从FileChannel中map()出来的,为 什么它又不提供unmap()呢?SUN自己也没有讲清楚为什么。O'Reilly的&&Java NIO&&中说是因为"安全"的原因,但是到底unmap()会怎么不安全,作者也没有讲清楚。
在sun网站也有相应的BUG报告:bug id:4724038链接为,但是sun自己不认为是BUG,而只是一个RFE(Request For Enhancement),有待改进。
好在有个叫bellomi的网友提出了一个解决方法,我也测试过,可以实现期望的功能。具体实现代码如下:
public static void clean(final Object buffer) throws Exception {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Method getCleanerMethod = buffer.getClass().getMethod("cleaner",new Class[0]);
getCleanerMethod.setAccessible(true);
sun.misc.Cleaner cleaner =(sun.misc.Cleaner)getCleanerMethod.invoke(buffer,new Object[0]);
cleaner.clean();
} catch(Exception e) {
e.printStackTrace();
不知道为什么SUN不提供ByteBuffer的派生。毕竟这是一个很实用的类,如果允许派生,那么我就可以操作的就不仅仅限于堆内存和文件了,我可以扩展到任何存储设备。
浏览: 477667 次
来自: 北京
标题写的就有点问题吧
不错哦!值得参考学习!
可以把数据库给我看一眼吗
细节不到位,如spring容器和spring mvc容器的关系 ...
总结的很好

我要回帖

更多关于 判断文件读取结束 的文章

 

随机推荐