铂西学习日记---New IO

1、为什么要使用NIO?
NIO是JDK1.4加入的新包,NIO的创建目的是为了让Jva程序员可以实现高速IO而无需编写自定义的本机代码。NIO将最耗时的/操作(即填充和提取缓冲区)转移回操作系统,因而可以极人地提高速度。


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

3、缓冲区
在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接语读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问NIO中的数据,您都是将它放到缓冲区中。
缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不仅仅是数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。
4、缓冲区类型
最常用的缓冲区类型是ByteBuffer。一个ByteBuffer可以在其底层字节数组上进行get/set操作(即字节的获取和设置)。ByteBuffer不是NIO中唯一的缓冲区类型。事实上,对于每一种基本的Java类型都有一种缓冲区类型:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer等。

 

示例:

import java.nio.ByteBuffer;

public class io_new_io_demo {
    public static void main(String[] args) {
        //在C中,‘allocate’表示分配内存空间,同样的,在这表示分配缓存空间
        ByteBuffer buf = ByteBuffer.allocate(8);//创建一个字节缓冲区,申请一个内存空间为8字节
        //查看原始状态
        System.out.println("position="+buf.position());//指向存储的位置,一开始为0,存储后,向后依次移动,0
        System.out.println("limit="+buf.limit());//限制,8
        System.out.println("capacity="+buf.capacity());//最大容量,8
        System.out.println("--------------------------------");

        //向缓冲区写入数据
        buf.put((byte) 10);
        buf.put((byte) 20);
        buf.put((byte) 30);
        buf.put((byte) 40);

        //查看插入数据后的状态
        System.out.println("position="+buf.position());//4
        System.out.println("limit="+buf.limit());//8
        System.out.println("capacity="+buf.capacity());//8
        System.out.println("--------------------------------");

        //缓冲区没有将数据放满,缓冲区反转(截取),就是截取带有真实数据的字节数组
        buf.flip();
        //查看反转后的状态
        System.out.println("position="+buf.position());//0
        System.out.println("limit="+buf.limit());//4
        System.out.println("capacity="+buf.capacity());//8

        //告知当前元素和限制之间是否有元素,即 position != limit ? true:false
        if(buf.hasRemaining()){
            //返回当前位置与限制之间的元素个数
            for (int i=0;i<buf.remaining();i++){
                //取出数据
                byte b = buf.get(i);
                System.out.println(b);
            }
        }
    }
}

 5、通道Channel

Channel是一个对象,可以通过它读取和写入数据,拿NIO与IO作比较,通道就像是流。正如前面提到的,所有数据都是通过Buffer对象来处理,您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或多个字节的缓冲区。同样,您不会从通道中读取字节,而是将数据从通道读入缓冲区,再从缓存区中获取这个字节。

示例:

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class io_13_nio_copeFileDemo2 {
    public static void main(String[] args) {
//        nioCopy();
        randomAccessFileCopy();
    }

    /**
     * IO操作的性能比较
     * 1.最快:内存映射
     * 2.其次:NIO读写
     * 3.然后:使用了缓存的IO
     * 4.最后:无缓存的IO流
     */
    /**
     * 通过内存映射实现文件的复制
     */
    public static void randomAccessFileCopy(){
        try {
            //读
            RandomAccessFile in = new RandomAccessFile("1.txt","r");
            //写
            RandomAccessFile out = new RandomAccessFile("2.txt","rw");
            //文件通道
            FileChannel fcIn = in.getChannel();
            FileChannel fcOut = out.getChannel();
            /**
             * 映射
             */
            long size = fcIn.size();//输入流的字节大小
            //输入输出流(映射方式)的缓冲区 FileChannel.MapMode.READ_ONLY表示类型为只读 READ_WRITE 可读可写
            MappedByteBuffer inBuf = fcIn.map(FileChannel.MapMode.READ_ONLY,0,size);
            MappedByteBuffer outBuf = fcOut.map(FileChannel.MapMode.READ_WRITE,0,size);

            for(int i=0;i<size;i++){
                outBuf.put(inBuf.get(i));
            }

            //关闭---关闭通道时会写入数据块
            fcIn.close();
            fcOut.close();
            in.close();
            out.close();
            System.out.println("Success!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 通过文件通道实现文件的复制
     */
    public static void nioCopy() {
        try {
            /**
             * 通道
             */
            //创建一个输入文件的通道
            FileChannel fcIn = new FileInputStream("1.txt").getChannel();
            //创建一个输出文件的通道
            FileChannel fcOut = new FileOutputStream("2.txt").getChannel();
            /**
             * 缓冲区
             */
            //创建一个缓冲区,申请1024个字节内存
            ByteBuffer buf = ByteBuffer.allocate(1024);
            while (fcIn.read(buf)!=-1){
                //数据反转,一块数据
                buf.flip();
                //已经反转,无需写到 0-->len
                fcOut.write(buf);
                //清空
                buf.clear();
            }
            //关闭流
            fcIn.close();
            fcOut.close();
            System.out.println("Success!");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

NIO可以提高读取数据的根本原因是利用了操作系统(如Linux)底层的IO多路复用机制

  6、NIO的工具类

JDK1.7引入了新的I0操作类,java.nio.file包 下,Java NIO Path接口和Files类


①Path接口
1、Path表示的是一个目录名序列,其后还可以跟着一个文件名,路径中第一个部件是根部件时就是
绝对路径,例如/或C:\,而允许访问的根部件取诀于文件系统; 
2、以根部件开始的路径是绝对路径,否则就是相对路径;
3、静态的Paths.get方法接受- 一个或多个字符串,字符串之间自动使用默认文件系统的路径分隔符连接
起来(Unix是 /, Windows是\),这就解决了跨平台的问题,接着解析连接起来的结果,如果不
是合法路径就抛出InvalidPathException异常,否则就返回-个Path对象

②Files工具类

static path write(Path path, byte[] bytes, OpenOption... options)---写入文件

static byte[] readAllBytes(Path path)---读取文件中的所有字节。

static path copy(Path source, Path target, CopyOption... options)---复制文件

static path move(Path source, Path target, CopyOption... options)---剪切文件

static void delete(Path path) ---如果path不存在文件将抛出异常,此时调用下面的比较好

static boolean deletelfExists(Path path)---删除文件

Files.createDirectory(path);---创建新目录,除了最后一个部件,其他必须是已存在的

Files.createDirectories(path);---创建路径中的中间目录,能创建不存在的中间部件

Files.createFile(path);---创建一个空文件,检查文件存在,如果已存在则抛出异常而检查文件存在是原子性的,因此在此过程中无法执行文件创建操作

Path newPath = Files.createTempFile(dir, prefix, suffix);

Path newPath = Files.createTempDirectory(dir, prefix);---添加前/后缀创建临时文件或临时目录

......

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

public class io_13_nio_pathFilesDemo {
    public static void main(String[] args) {
        File file = new File("d:\\1.txt");
        //path
        Path p1 = Paths.get("d:\\","1.txt");//调用的p3的哪个方法,和p3一样
        Path p2 = file.toPath();
        Path p3 = FileSystems.getDefault().getPath("d:\\","1.txt");

        //files工具类
        Path p4 = Paths.get("1.txt");
        // StandardOpenOption.APPEND 表示追加
        try {
            //写入文件
            Files.write(p4,"lsq666啊实打实".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);

            //读取文件
//            byte[] bytes = Files.readAllBytes(p4);
//            System.out.println(new String(bytes));

            //复制文件 StandardCopyOption.REPLACE_EXISTING 表示如果存在就替换
//            Files.copy(p4,Paths.get("3.txt"),StandardCopyOption.REPLACE_EXISTING);

            //剪切文件
//            Files.move(p4,Paths.get("3.txt"),StandardCopyOption.REPLACE_EXISTING);

            //删除文件
//            Files.delete(p4);
//            Files.deleteIfExists(p4);

            //创建新目录,除了最后一个部件,其他必须是已存在的
//            Files.createDirectory(Paths.get("c:\\test\\lsq.jpg"));
            //创建路径中的中间目录,能创建不存在的中间部件
//            Files.createDirectories(Paths.get("c:\\test\\lsq.jpg"));
            //创建一个空文件,检查文件存在,如果已存在则抛出异常,因为检查文件存在是原子性的,因此在此过程中无法执行文件创建操作
//            Files.createFile(Paths.get("c:\\test\\lsq.jpg"));
            
            
             //添加前/后缀创建临时文件或临时目录
//             Path newPath = Files.createTempFile(dir, prefix, suffix);
//             Path newPath = Files.createTempDirectory(dir, prefix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小狗铂西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值