IO流NIO
Posted yimengxianzhi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IO流NIO相关的知识,希望对你有一定的参考价值。
IO流:
a、I是指Input(输入),O是指Output(输出)
b、在Java中,文件的输入输出是通过流来实现的,用来实现程序或进程间的通信,或读写外围设备,文件等
c、一个流,必有源端和目的端,它们可以是计算机内存的某区域,也可以是磁盘文件,甚至可以是Internet上的某个URL,对于流而言,我们不用关心数据是如何传输的,只需要向源端输入数据,向目的端获取数据即可。
d、流按照处理数据的单位,可以分为字节流和字符流,按照流向分为输入流和输出流
字节流:用于操作字节为单位的二进制文件文件(音频 视频 图片 docx等,用记事本打开是乱码的文件一般就是字节流)
常用方法:
FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { //输入流 fileInputStream = new FileInputStream("C:/Java_Tools/image/hello.jpg"); //输出流 fileOutputStream = new FileOutputStream("C:/Java_Tools/hello.jpg"); byte[] car = new byte[1024]; int length = 0; //当读取数据为-1了,读取结束 while((length=fileInputStream.read(car))!=-1){ fileOutputStream.write(car,0,length); } //冲刷缓存 fileOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); }finally{ if(fileInputStream!=null){ try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if(fileOutputStream!=null){ try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
字符流:将字节转换为2个字节的Unicode字符就有了字符流,用于操作字符文件(记事本等)
常用方法:
FileReader fileReader null; FileWriter fileWriter = null; try { //输入流 fileReader = new FileReader("C:/Java_Tools/log.log"); //输出流 fileWriter = new FileWriter("C:/Java_Tools/image/log.log"); char[] car = new char[1024]; int length = 0; while((length=fileReader.read(car))!=-1){ fileWriter.write(car,0,length); } fileWriter.flush(); } catch (Exception e) { e.printStackTrace(); }finally{ if(fileReader!=null){ try { fileReader.close(); } catch (Exception e) { e.printStackTrace(); } } if(fileWriter!=null){ try { fileWriter.close(); } catch (Exception e) { e.printStackTrace(); } } }
缓冲流——数据在复制过程中会从磁盘中获取,有一个缓冲区
缓冲字节流:实现字节为单位的二进制文件
输入流:BufferedInputStream
输出流:BufferedOutputStream
缓冲字符流:实现2个字节的字符文件
输入流:BufferedReader
输出流:BufferedWriter
转换流:由于文件自身编码方式和程序运行时使用的默认编码方式不一致,致使程序读取或输出字符文件时可能会出现乱码,这时可以使用字节流操作文件,然后再讲字节流转换成字符流
字节输入流——>字符输入流:InputStreamReader
字节输出流——>字符输出流:OutputStreamWriter
NIO(NEW IO):
NIO提供多路非阻塞式的高伸缩性网络I/O,从而提高了效率,NIO主要有三大核心组件:Channel、Buffer、Selector,重点介绍前两者
Buffer:Buffer是一个抽象类,Buffer类型变量对应的对象代表一块缓冲区,ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer类都是Buffer抽象类的子类,其中ByteBuffer最常用
常用方法:
a、static ByteBuffer allocate(int capacity):分配一个新的字节缓冲区
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); } }
b、int capacity() :返回此缓冲区的容量,实际上直接将capacity成员属性值返回。
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); System.out.println(bytebuffer.capacity()); } } //输出结果:1024
c、ByteBuffer put(byte b):将字节类型数据写入当前位置的缓冲区,然后position+1,位置从0开始
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); byte a=3; bytebuffer.put(a); } }
d、byte[] array() :将ByteBuffer类型的数据转为byte数组
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); byte a=3; bytebuffer.put(a); byte[] bbuf=bytebuffer.array(); } }
e、int position():返回缓冲区当前位置,实际上直接将position成员属性值返回。
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); System.out.println(bytebuffer.position()); byte a=3; bytebuffer.put(a); System.out.println(bytebuffer.position()); } } //输出结果:0 1
f、Buffer flip() :翻转缓冲区,将当前position值赋值给limit,并将position置零;这个方法主要防止在最后一次输出时,如果缓存区并未装满,则将position值赋值给limit即为当前缓冲区内数据量,一般搭配hasRemaining方法使用。如果没有limit属性而直接使用capacity,则会输出冗余数据。
源码分析:
举例:
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); bytebuffer.position(); byte a=3; bytebuffer.put(a); bytebuffer.position(); bytebuffer. flip(); bytebuffer.position(); } } //输出结果:0 1 0
g、byte get()读取缓冲区当前位置的字节,然后当前位置+1
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); bytebuffer.position(); byte a=3; bytebuffer.put(a); bytebuffer.position(); bytebuffer. flip(); bytebuffer.position(); bytebuffer.get(); } }
h、boolean hasRemaining():在释放缓冲区时告诉您是否已经达到缓冲区的上界
源码分析:
举例:
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); System.out.println(bytebuffer.position()); byte a=3; bytebuffer.put(a); System.out.println(bytebuffer.position()); System.out.println(bytebuffer.hasRemaining()); bytebuffer. flip(); bytebuffer.get(); System.out.println(bytebuffer.position()); System.out.println(bytebuffer.hasRemaining()); } } //输出结果:0 1 true 1 false
i、Buffer clear():将缓冲区重置为空状态。它并不改变缓冲区中的任何数据元素,而是仅仅将上界值初始化为容量的值,并把位置设回0。
源码分析:
举例:
public class Test { public static void main(String[] args) { ByteBuffer bytebuffer=ByteBuffer.allocate(1024); bytebuffer.position(); byte a=3; bytebuffer.put(a); bytebuffer.clear(); System.out.println(bytebuffer.get()); System.out.println(bytebuffer.position()); System.out.println(bytebuffer.hasRemaining()); } } //输出结果:3 1 true
Channel:一个接口,该接口类型变量指向的对象代表一个数据传输通道,Channel对象是面向缓冲区的:数据总是从通道读取到缓冲区(Buffer类型对象),或从缓冲区(Buffer类型对象)写入到通道中
常用方法:
a、FileChannel:从文件中读写数据。
b、DatagramChannel:通过UDP读写网络中的数据。
c、SocketChannel:通过TCP读写网络中的数据。
d、ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样,对每一个新进来的连接都会创建一个SocketChannel。
public class Test { public static void main(String[] args) { try { FileInputStream fileInputStream=new FileInputStream("C:/Java_Tools/log.log"); FileChannel inChannel=fileInputStream.getChannel(); FileOutputStream fileOutputStream=new FileOutputStream("C:/Java_Tools/image/log.log"); FileChannel ouChannel=fileOutputStream.getChannel(); ByteBuffer byteBuffer= ByteBuffer.allocate(1024); while(inChannel.read(byteBuffer)!=-1) { byteBuffer.flip(); ouChannel.write(byteBuffer); byteBuffer.clear(); } } catch (Exception e) { e.printStackTrace(); } } }
以上是关于IO流NIO的主要内容,如果未能解决你的问题,请参考以下文章
java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段
java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段