Day17:NIO流、异常

本文介绍了Java NIO流和异常处理相关知识。NIO通过selector管理IO事件,面向缓冲区,包含Buffers、Channels、Selectors等核心部分。异常分为Exception和Error类,介绍了常见异常类型,还阐述了异常处理机制、抛出异常的方式以及自定义异常类的方法。

一、NIO流

NIO:主要是通过selector选择器管理所有的IO事件,服务端为例:首先需要serverSoketChannel.open();获得一个channel然后通过channel.configureBlocking(false);设置非阻塞再通过channel.socket();获取一个Serversocket,然后通过bing()绑定端口,后打开选择器 selector.open();通过channel.register(selector,key);注册通道。后通过selector.select();监听key.
NIO(同步非阻塞):面向缓冲区;

Java NIO 由以下几个核心部分组成:

  • Buffers -- 缓冲区 :针对系统的缓冲区
  • Channels -- 通道 : 类似于BIO里面的流
  • Selectors -- 选择器
    FileOutputStream fos = new FileOutputStream("test.txt");
    FileChannel channel = fos.getChannel();

下面是JAVA NIO中的一些主要Channel的实现:

  • FileChannel : 文件通道
  • DatagramChannel : UDP通道
  • SocketChannel : TCP客户端通道
  • ServerSocketChannel : TCP 服务端通道

以下是Java NIO里关键的Buffer实现:

  • ByteBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer
  • CharBuffer

 

创建缓冲区:ByteBuffer allocate = ByteBuffer.allocate(int a);

获得指针:allocate.position()

获得限制:allocate.limit()

获得容量:allocate.capacity()

写入数据:put(byte) or put(byte[])

反转:flip() ;反转此缓冲区:将指针初始化,限制为数据的长度

remaining()获取到指针与限制之间的元素数量

 BIO是一个连接一个线程。

  NIO是一个请求一个线程。

  AIO是一个有效请求一个线程。

    ByteBuffer buffer = ByteBuffer.allocateDirect(10);
	System.out.println("获取指针位置:"+buffer.position());//0
	System.out.println("获取限制位置:"+buffer.limit());//10
	System.out.println("获取容量位置:"+buffer.capacity());//10
	System.out.println("---------------------");
		
	buffer.put("123456".getBytes());
	System.out.println("获取指针位置:"+buffer.position());//6
	System.out.println("获取限制位置:"+buffer.limit());//10
	System.out.println("获取容量位置:"+buffer.capacity());//10
	System.out.println("---------------------");
		
	buffer.flip();//置反,指针归零,限制到原指针位置
	System.out.println("获取指针位置:"+buffer.position());//0
	System.out.println("获取限制位置:"+buffer.limit());//6
	System.out.println("获取容量位置:"+buffer.capacity());//10
	System.out.println("---------------------");
		
	//读取 remaining()读取指针到限制的有效字节
	for (int i = 0; i <buffer.remaining(); i++) {
		System.out.print((char)buffer.get(i));
	}

NIO拷贝文件的两种方式:创建BIO ==》 获取NIO通道 ==》 开辟缓冲区 ==》拷贝 ==》关流

1、BIO---FileInputStream

//一次性拷贝buffer
	File file = new File("调音师.mkv");
	FileInputStream fis = new FileInputStream(file);
	FileOutputStream fos = new FileOutputStream("调音师-副本.mkv");
		
//通过BIO流的对象获取NIO流的通道
	FileChannel rChannel = fis.getChannel();
	FileChannel wChannel = fos.getChannel();
		
//开辟缓存区
	ByteBuffer buffer = ByteBuffer.allocate(1024);
		
//拷贝
	while(rChannel.read(buffer)!=-1) {
		buffer.flip();
		wChannel.write(buffer);
		buffer.clear();
	}
		
//关流
	fis.close();
	fos.close();

2、BIO--RandomAccessFile

//源文件
	File file = new File("调音师.mkv");
	long len = file.length();
	
//创建BIO
	RandomAccessFile rRaf = new RandomAccessFile(file, "r");
	RandomAccessFile wRaf = new RandomAccessFile("调音师-副本.mkv","rw");
		
//获取NIO的管道
	FileChannel rChannel = rRaf.getChannel();
	FileChannel wChannel = wRaf.getChannel();
		
//开辟缓冲区
	MappedByteBuffer rMap = rChannel.map(MapMode.READ_ONLY, 0, len);
	MappedByteBuffer wMap = wChannel.map(MapMode.READ_WRITE, 0, len);
	
//拷贝
	for (int i = 0; i < len; i++) {
		byte b = rMap.get(i);
		wMap.put(b);
	}
		
//关流
	rRaf.close();
	wRaf.close();

 

二、异常

异常可分为两大类:java.lang.Exception类与java.lang.Error类。这两个类均继承自java.lang.Throwable类。

IOException  extends  Exception

RuntimeException  extends  Exception

习惯上将Error与Exception类统称为异常类,但两者本质还是不同的。Error类专门用来处理严重影响程序运行的错误,可是通常程序设计者不会设计程序代码去捕捉这个错误,其原因在于即使捕捉到它,也无法给予适当的处理。

 

异常也称为例外,是在程序运行过程中发生的、会打断程序正常执行的事件。下面是几种常见的异常:

内存溢出的错误(OutOfMemoryError):创建对象,并存入集合中,此对象不会被释放资源

栈内存溢出(StackOverflowError):调用方法,就会在栈内开辟空间,死循环的调用方法,栈就会被装满

算术异常(ArithmeticException)

空指针异常(NullPointerException);没有给对象开辟内存空间时

找不到文件异常(FileNotFoundException)

运行时异常(RunntimeException)非受检性异常:那些程序员在编写程序的时,应该避免的异常(逻辑异常),编译器不要求强制处置的异常

类型转换异常(ClassCastException):(注意:下转型一定用instanceof判断)

下标越界异常(ArrayIndexOutOfBoundsException)

受检(checked)异常 --- 一般性异常:编译器要求必须处置的异常。指的是程序在运行时由于外界因素造成的一般性异常。

文件未找到的异常(FileNotFoundException)

IOException IO流的异常

ClassNotFoundException:类未找到异常

Java的异常处理机制也秉持着面向对象的基本思想。在Java中,所有的异常都是以类的类型存在。除了内置的异常类之外,Java也可以自定义异常类。此外,Java的异常处理机制也允许自定义抛出异常。

2.1为何需要异常处理

异常是在程序运行过程中发生的事件,比如算术异常,数组越界,文件找不到等,这些事件的发生将阻止程序的正常运行。为了加强程序的健壮性,在程序设计时,必须考虑到可能发生的异常事件,并作出相应的处理。

2.2异常的处理

异常发生后,Java便把这个异常抛出来,如果抛出来之后没有程序代码去捕捉它,程序便终止。如果加上捕捉异常的程序代码,则可针对不同的异常做妥善的处理,这种处理的方式称为异常处理。

try{

···要检查的代码块···

}catch(异常类   对象名称){

          异常发生时的处理语句;

}finally{

          一定会运行到的程序代码;

}

处理步骤:

  1. try程序块若是有异常发生,程序的运行便中断,并抛出“异常类所产生的对象”;
  2. 抛出的对象如果属于catch()括号内欲捕获的异常类,catch则会捕捉此异常,然后进到catch的块里继续运行。
  3. 无论try程序块是否捕捉到异常,或者捕捉到的异常是否catch()括号里的异常相同,最后一定会运行finally块里的程序代码。

在异常捕捉的过程中做了两个判断:第1个是try程序块是否有异常产生,第2个是产生的异常是否和catch()括号内捕捉的异常相同。

finally块是可以省略的。如果省略finally块不写,那么在catch()块运行结束后,程序将跳到try-catch块之后继续执行。

    FileInputStream fis = null;
	FileOutputStream fos = null;
	try {
		fis = new FileInputStream("调音师.mkv");
		fos = new FileOutputStream("调音师-副本.mkv");
		byte[] b = new byte[1024];
		int len;
		while((len = fis.read(b))!=-1) {
			fos.write(b, 0, len);
		}
	}catch(FileNotFoundException e){
		System.out.println("文件未找到异常");
	}catch(IOException e) {
		System.out.println("IO流异常");
	}finally {
		if(fis!=null) {
			try{
				fis.close();
			}catch(IOException e) {}
		}
		if(fos!=null) {
			try{
				fos.close();
			}catch(IOException e) {}
		}
	}

以下方式不用主动关闭流

//执行完了try..catch..就自动关流
	try (FileInputStream fis = new FileInputStream("调音师.mkv");
		FileOutputStream fos = new FileOutputStream("调音师-副本.mkv")){
		byte[] b = new byte[1024];
		int len;
		while((len = fis.read(b)) != -1){
			fos.write(b, 0, len);
		}
	} catch (FileNotFoundException e) {
		System.out.println("文件未找到异常");
	} catch (IOException e) {
		System.out.println("IO流异常");
	}

出现多个异常的处理方式:

    try {
		System.out.println(10/0);
		String str =null;
		System.out.println(str.equals("xxx"));	
	}catch(ArithmeticException | NullPointerException e){
		System.out.println("异常出现了");
	}

 

2.3抛出异常

1.在程序中抛出异常

在程序抛出异常时,一定要用到throw这个关键词。

throw 异常类实例对象。throw语句必须使用new关键字来产生对象。

2.指定方法抛出异常

方法名称(参数...)  throws  异常类1,异常类2,...

抛出的异常交给调用的方法去处理

2.4自定义异常类

所有可处理的异常类均继承自Exception类,所以自定义异常类也必须继承这个类。

class  异常名称 extends Exception

{

   .....

}

//自定义异常类
public class MyException extends Exception{

	
	private static final long serialVersionUID = 8123594069232603221L;

	@Override
	public String toString() {
		return "除数不能为0的异常";
	}
}
    //手动抛异常,自定义异常类
    Scanner scan = new Scanner(System.in);
	int num1 = scan.nextInt();
	int num2 = scan.nextInt();
		
	try {
		if(num2==0) {
			throw new MyException();
		}
	}catch(MyException e) {
		System.out.println(e);
		num2=1;
	}
		
	System.out.println(num1/num2);

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值