NIO2提供两种主要的文件读取方法:
使用buffer和channel类
使用Path 和 File 类
NIO读取文件有以下三种方式:
1. 旧的NIO方式,使用BufferedReader
import java.io.BufferedReader
import java.io.FileReader
import java.io.IOException
public class WithoutNIOExample
{
public static void main(String[] args)
{
BufferedReader br = null
String sCurrentLine = null
try
{
br = new BufferedReader(
new FileReader("test.txt"))
while ((sCurrentLine = br.readLine()) != null)
{
System.out.println(sCurrentLine)
}
}
catch (IOException e)
{
e.printStackTrace()
}
finally
{
try
{
if (br != null)
br.close()
} catch (IOException ex)
{
ex.printStackTrace()
}
}
}
}
2. 使用buffer读取小文件
import java.io.IOException
import java.io.RandomAccessFile
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
public class ReadFileWithFileSizeBuffer
{
public static void main(String args[])
{
try
{
RandomAccessFile aFile = new RandomAccessFile(
"test.txt","r")
FileChannel inChannel = aFile.getChannel()
long fileSize = inChannel.size()
ByteBuffer buffer = ByteBuffer.allocate((int) fileSize)
inChannel.read(buffer)
buffer.rewind()
buffer.flip()
for (int i = 0i <fileSizei++)
{
System.out.print((char) buffer.get())
}
inChannel.close()
aFile.close()
}
catch (IOException exc)
{
System.out.println(exc)
System.exit(1)
}
}
}
3. 分块读取大文件
import java.io.IOException
import java.io.RandomAccessFile
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
public class ReadFileWithFixedSizeBuffer
{
public static void main(String[] args) throws IOException
{
RandomAccessFile aFile = new RandomAccessFile
("test.txt", "r")
FileChannel inChannel = aFile.getChannel()
ByteBuffer buffer = ByteBuffer.allocate(1024)
while(inChannel.read(buffer) >0)
{
buffer.flip()
for (int i = 0i <buffer.limit()i++)
{
System.out.print((char) buffer.get())
}
buffer.clear()// do something with the data and clear/compact it.
}
inChannel.close()
aFile.close()
}
}
4. 使用MappedByteBuffer读取文件
import java.io.RandomAccessFile
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
public class ReadFileWithMappedByteBuffer
{
public static void main(String[] args) throws IOException
{
RandomAccessFile aFile = new RandomAccessFile
("test.txt", "r")
FileChannel inChannel = aFile.getChannel()
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size())
buffer.load()?
for (int i = 0i <buffer.limit()i++)
{
System.out.print((char) buffer.get())
}
buffer.clear()// do something with the data and clear/compact it.
inChannel.close()
aFile.close()
}
}
io,也称old io,读取文件主要通过流,从磁盘上一个一个字符的读,效率比较低下。nio,在对文件 *** 作下改进了方式,通过块读取,一整块一整块的读取,所以读取出来的不会是一个字符,而是一个块,把这些数据放到内存缓冲区内。在进行 *** 作。通过块的读取来提高速度。(块 *** 作,fileChannel)
内存映射,MappedByteBuffer,这个主要是通过内存映射,即利用虚拟内存(把文件某一部分当成内存),直接 *** 作文件,对于一些要在内存中大块 *** 作的文件,比如1G的文件
你要在内存中 *** 作200M的部分,,把200M读到物理内存是比较耗内存和CPU的,不如直接把那部分文件虚拟成内存直接 *** 作。
下面是对用以上三个文式对一个300M的文件进行读取,并写入另一个文件的测试:
1. inputstream CPU5.6% 内存2.6M costTime:4.039S 使用缓冲区byte:4kb
2. filechannelCPU1.3% 内存2.6M costTime:3.359S 使用缓冲区byte:0(transferTo方式)
3. MappedByteBufferCPU6.9% 内存2.4M costTime:6.966S 内存映射:300M
可见对大文件块读取是最好的如果要直接 *** 作文件的很大的一部分的内容,则比较适合MappedByteBuffer 如读取很小的内容,比如8B的内容,inputStream可能是最好的。
代码如下,选几个文件自已试下。使用jdk自带JConsole进行观察。
public class Test {
public static void main(String[] args)throws Exception{
File ff=new File("F:/workspace/pureMQ/src/mq/pure/file/cc.rar")
File[] f=new File[7]
File[] f_write=new File[7]
Thread.sleep(15000)
for(int i=0i<7i++){
f[i]=new File("F:/workspace/pureMQ/src/mq/pure/file/1"+(i+1)+".jpg")
}
for(int i=0i<7i++){
f_write[i]=new File("F:/workspace/pureMQ/src/mq/pure/file/"+i+".jpg")
if(!f_write[i].exists()){
f_write[i].createNewFile()
}
}
f[0]=ff
long begin=System.currentTimeMillis()
int choice=1
for(int i=0i<7i++){
switch(choice){
case 1:
System.out.println("1")
InputStream ips=new FileInputStream(f[i])
OutputStream ops=new FileOutputStream(f_write[i])
byte[] b=new byte[4096]
int index
while((index=ips.read(b))!=-1){
ops.write(b)
}
if(ips!=null){
ips.close()
}
if(ops!=null){
ops.close()
}
break
case 2:
System.out.println("2")
RandomAccessFile raf=new RandomAccessFile(f[i],"r")
RandomAccessFile raf_write=new RandomAccessFile(f_write[i],"rw")
FileChannel fc=raf.getChannel()
FileChannel fc_write=raf_write.getChannel()
fc.transferTo(0, fc.size(), fc_write)
fc.close()
fc_write.close()
raf.close()
raf_write.close()
break
case 3:
System.out.println("3")
RandomAccessFile raf2=new RandomAccessFile(f[i],"r")
RandomAccessFile raf2_write=new RandomAccessFile(f_write[i],"rwd")
FileChannel fc2=raf2.getChannel()
FileChannel fc2_write=raf2_write.getChannel()
MappedByteBuffer mbb=fc2_write.map(MapMode.READ_WRITE, 0, fc2.size())
ByteBuffer bb=ByteBuffer.allocate(4096)
while(fc2.read(bb)!=-1){
bb.flip()
mbb.put(bb)
bb.compact()
}
mbb.force()
fc2.close()
fc2_write.close()
raf2.close()
raf2_write.close()
break
default:
break
}
}
long end=System.currentTimeMillis()
System.out.println("all time cost:"+ (end-begin))
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)