java中NIO基本概念与使用

NIO是JDK1.4加入的新包,目的是是可以让程序员可以实现高速I/O而无需编写自定义的本机代码。

NIO将最耗时的I/O操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。

流与块的比较
原来的I/O库(在java.io.*中)与NIO的区别: 数据打包和传输的方式不同,原来的I/O以流的方式处理数据,而NIO以块的方式处理数据。
面向流的I/O系统一次一个字节地处理数据。每一个操作都在一步中产生或者消费一个字节数据。。因此面向流的I/O通常比较慢。
面向块的I/O系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按流(字节)处理数据要快得多。但是面向块的I/O缺少一些面向流的I/O所具有的优雅性和简单性。

缓冲区
在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区的,在写入数据时,它是写入到缓冲区的。任何时候访问NIO中的数据,都将它放到缓冲区。
缓冲区实质是一个数组。通常它是一个字节数组,但是也可以使用其他类型的数组。但是一个缓冲区不仅仅是一个数组。缓冲区提供了对数据的结构化访问,还可以跟踪系统的读/写进程。

缓冲区类
最常用的缓冲区类型是ByteBuffer。一个ByteBuffer可以在其底层字节数组上进行get/set操作(即字节的获取和设置)。ByteBuffer不是NIO中唯一的缓冲区类型。事实上,对于每一种基本java数据类型(除了布尔值)都有一种缓冲区类型

缓冲区状态变量
指定缓冲区在任意时刻的三个状态值:
position(位置):缓冲区的位置
limit(容量):缓冲区的容量大小
capacity(上限):缓冲区的实际上限(设定好了不变的)

代码示例:

package com.booy;

import java.nio.ByteBuffer;

public class NIODemo {

	public static void main(String[] args) {
		//创建一个字节缓冲区,申请8字节的内存空间
		ByteBuffer bf = ByteBuffer.allocate(8);
		//向缓冲区写入数据
		bf.put((byte) 10);
		bf.put((byte) 20);
		bf.put((byte) 30);
		bf.put((byte) 40);
		System.out.println("缓冲区当前位置:"+bf.position());
		System.out.println("缓冲区容量:"+bf.limit());//有效字节+空容量
		System.out.println("缓冲区实际上限:"+bf.capacity());
		System.out.println("---------------");
		
		//缓冲区反转,不改变缓冲区数据,修改了位置和缓冲区容量
		bf.flip();
		System.out.println(bf.position());
		System.out.println(bf.limit());
		System.out.println(bf.capacity());
		//当前位置和限制之间是否有元素
		if(bf.hasRemaining()) {
			//当前位置和限制之间元素个数
			for(int i=0; i<bf.remaining();i++) {
				byte b =bf.get(i);
				System.out.println(b);
			}
		}
	}
}

通道:Channel
是一个对象,可以通过它读取和写入数据,就像是原来I/O中的流。
所有数据都是通过Buffer对象来处理,永远不会将字节直接写入到通道中,反而是将数据写入到缓冲区(或从缓冲区读取数据)中,由缓冲区操作。

比较IO操作的性能:
1、内存映射最快
2、NIO读写文件
3、使用了缓存的IO流
4、无缓存的IO流

package com.booy;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

public class ChannelCopyFileDemo {

	public static void main(String[] args) {
		try {
			copyFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private static void copyFileMap() throws Exception{
		//使用RandomAccessFile工具类加内存映射实现文件复制功能 
		//构建输入流
		RandomAccessFile rIn= new RandomAccessFile("D:\\test\\1.jpg","r");
		RandomAccessFile rOut= new RandomAccessFile("D:\\1.jpg","rw");
		//构建通道
		FileChannel chIn = rIn.getChannel();
		FileChannel chOut = rOut.getChannel();
		
		long size= chIn.size();//输入流的字节大小
		//内存映射
		MappedByteBuffer inBuf =chIn.map(MapMode.READ_ONLY, 0, size);
		MappedByteBuffer outBuf =chIn.map(MapMode.READ_WRITE, 0, size);
		
		for(int i=0;i<size;i++) {
			outBuf.put(inBuf.get());
		}
		//关闭通道时会写入数据块
		chIn.close();
		chOut.close();
		rIn.close();
		rOut.close();
		System.out.println("copy success!");	

	}
	//NIO读写文件方式复制文件
	private static void copyFile() throws IOException {
		FileChannel chIn = new FileInputStream("D:\\test.zip").getChannel();//构建通道
		FileChannel chOut = new FileOutputStream("D:\\test\\test.zip").getChannel();
		
		ByteBuffer bytes = ByteBuffer.allocate(1024);//字节缓冲区
		while(chIn.read(bytes)!=-1) {
			bytes.flip();
			chOut.write(bytes);
			bytes.clear();//清空缓冲区
		}
		chIn.close();
		chOut.close();
		System.out.println("文件复制成功");
	}
}

Path接口与Files工具类
JDK1.7引入了新的IO操作类,java.nio.file包下,java NIO Path接口和Files类

Path接口
1、Path表示一个目录名序列,其后可以跟着一个文件名,路径中第一个部件是根部件时就是绝对路径,如/或c:\,而允许访问的根部件取决于文件系统;否则就是相对路径。

2、静态的Path.get方法接受一个或多个的字符串,字符串之间自动使用默认文件系统的路径分隔符连接起来(Unix是/,Windows是\),这就解决了跨平台的问题,接着解析连接起来的结果,如果不是合法路径就抛出InvalidPathException异常,否则就返回一个Path对象。
代码示例:

package com.booy;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;

public class NIOFilesDemo {

	public static void main(String[] args) {
		File file = new File("D:\\test\\1.jpg");
		
		//path
		Path p1 = Paths.get("D:\\test","1.jpg");
		System.out.println(p1);
		
		Path p2 = file.toPath();
		System.out.println(p2);
		
		Path p3 = FileSystems.getDefault().getPath("D:\\test","1.jpg");
		System.out.println(p3);
		
		//files工具类使用
		Path p4 = Paths.get("D:\\test","test.txt");
		String s = "小乔流水人家";
		try {
			//写文件操作,StandardOpenOption.APPEND表示追加
			Files.write(p4, s.getBytes(), StandardOpenOption.APPEND);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			//读文件操作
			byte[] bytes = Files.readAllBytes(p4);
			System.out.println(new String(bytes));
		} catch (IOException e) {
			e.printStackTrace();
		}
//		try {
//			//文件的复制,StandardCopyOption.REPLACE_EXISTING表示替换
//			Files.copy(p3, Paths.get("D:\\1.jpg"), StandardCopyOption.REPLACE_EXISTING);
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		try {
//			//文件的移动
//			Files.move(p3, Paths.get("D:\\1.jpg"), StandardCopyOption.REPLACE_EXISTING);
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		try {
		//文件的删除
//			Files.delete(p3);
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		try {
//			//创建目录
//			Files.createDirectory(Paths.get("D:\\test\\booy\\1"));
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		try {
//			//创建多级目录
//			Files.createDirectories(Paths.get("D:\\test\\booy\\2\\3"));
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
		try {
			//创建文件
			Files.createFile(Paths.get("D:\\test\\booy\\1.txt"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值