天天看点

JAVA NIO(New IO)使用和传统IO使用二、特立独行的RandomAccessFile三、NIO

一、传统IO流类结构设计:

JAVA NIO(New IO)使用和传统IO使用二、特立独行的RandomAccessFile三、NIO

传统IO设计是面向流(字节流或字符流)的,部分是有缓冲区的,对于没有缓冲区的流,为了提高效率,是需要我们自行使用缓冲区的。

ByteArrayOutputStream 内部用一个自动增长byte[]将数据保存起来,即使流被关闭,数据还是可以访问的,适合多次访问流的场景,一般输入流只能读一次。

ByteArrayInputStream 内部用一个自动增长的byte[]将数据保存起来,即使流被关闭,数据还是可以访问的,适合多次访问流的场景,一般输入流只能读一次。

BufferedOutputStream 具备缓冲能力的输出流

BufferedInputStream 具备缓冲能力的输入流

/**
 * 输入流拷贝到输出流
 *
 * @throws Exception
 */
void testCopyStream() throws Exception {
    FileInputStream fileInputStream = new FileInputStream("img/a.jpg");
    FileOutputStream fileOutputStream = new FileOutputStream("img/a2.jpg");
    byte[] buf = new byte[1024];
    int len;
    // 这里的缓冲对输入和输出流都有作用
    while ((len = fileInputStream.read(buf)) != -1) {
        fileOutputStream.write(buf, 0, len);
    }
    fileOutputStream.flush();
    fileInputStream.close();
    fileOutputStream.close();
}

/**
 * ByteArrayOutputStream功效,能将整个流内容存起来,后续继续构造一个输出或输入流重复使用,一般输入流只能读取一次,想重复使用需要自己保存内容
 * 输入流转换成String
 *
 * @throws Exception
 */
void testByteArrayStream() throws Exception {
    FileInputStream fileInputStream = new FileInputStream("text/a.txt");
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(10240);
    byte[] buf = new byte[2048];
    int len;
    while ((len = fileInputStream.read(buf)) != -1) {
        byteArrayOutputStream.write(buf, 0, len);
    }
    byteArrayOutputStream.flush();
    String content = byteArrayOutputStream.toString("UTF-8");
    System.out.println(content);
}

void testBufferedStream() throws Exception{
    FileInputStream fis = new FileInputStream("test");
    BufferedInputStream bis = new BufferedInputStream(fis);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    // 读取bis流中的下一个字节
    int c = bis.read();
    while (c != -1) {
        baos.write(c);
        c = bis.read();
    }
    bis.close();
    byte retArr[] = baos.toByteArray();
}
           

二、特立独行的RandomAccessFile

Java中有一个操作文件随机任意位置读写的类型,JDK1.0就有了,他就是RandomAccessFile。他并没有性能上的优势。

三、NIO

0、操作系统在与外部设备进行交互时,是需要发生系统中断的,此时用户进程(线程)会被挂起,内核操作完成后才会恢复用户程序,其中,用户程序是不直接与外部设备交互,用户程序和内核交互,内核与外部设备交互。

1、Java NIO中主要组件是Selector、Channel、Buffer,看到Selector就知道Java NIO的IO模型多路复用。

2、NIO的3个组件中用户编程最多的是Buffer,Buffer就是用户程序缓冲区的接口,背后他会与内核缓冲区进行数据交互,所以读、写操作就完全依赖Buffer的使用了。

3、创建Buffer时需要指定缓冲区的大小,这个大小最好比实际传输的消息大小略大一些。

4、Buffer有个flip()反转方法,用来反转Buffer的读、写状态,为什么需要这个方法?因为当你从Channel中读取数据时,对Buffer来说是写状态,Buffer被写完以后,需要从Buffer中读取到用户的业务程序中,这个时候对Buffer来说是读状态,需要调用flip()反转,所以由此看来,flip()方法一定不能少。

Channel实现,包含了文件IO和网络IO
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel

Buffers实现,包含了各个数据类型
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
           
// 读文件    
public static void readFile(File file) throws Exception{
    RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
    FileChannel channel = randomAccessFile.getChannel();
    // 传统IO用BufferedReader
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    channel.read(buffer);
    byte[] b = buffer.array();
    System.out.println(new String(b));
    channel.close();
    randomAccessFile.close();
}