javaSE基础知识——day16 新IO流,通道和缓冲区Files.copy()

Java NIO 的简介

Java NIO ( New IO )是从 Java 1.4 版本开始引入的一个新的 IO API ,
可以替代标准的 Java IO API 。
NIO 与原来的 IO 有同样的作用和目的,但是使用的方式完全不同, NIO 支持面向缓冲区的、基于通道的 IO 操作。
NIO 将以更加高效的方式进行文件的读写操作.

Java IO 与 NIO 的区别

IONIO
面向流(StreamOriented)面向缓冲区(BufferOriented)
阻塞IO(BlockingIO) BIO非阻塞IO(NonBlockingIO)
(无)选择器(Selectors)

通道(Channel )与缓冲区(Buffer)

Java NIO 系统的核心在于:通道 (Channel) 和缓冲区(Buffer)
通道表示打开到 IO 设备 ( 例如:文件、套接字 ) 的连接。若需要使用 NIO 系统,需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。

简而言之, Channel 负责传输, Buffer 负责存储

缓冲区( Buffer

缓冲区( Buffer ):一个用于特定基本数据类型的容器。由 java.nio 包定义的,所有缓冲区都是 Buffer 抽象类的子类。
Java NIO 中的 Buffer 主要用于与 NIO 通道进行交互,数据是从通道读入缓冲区,从缓冲区写入通道中的。

Buffer的常用方法

方法描述
Buffer clear()清空缓冲区并返回对缓冲区的引用
Buffer flip()将缓冲区的界限设置为当前位置,并将当前位置充值为0
int capacity()返回Buffer的capacity大小
boolean hasRemaining()判断缓冲区中是否还有元素
int limit()返回Buffer的界限(limit)的位置
Buffer limit(intn)将设置缓冲区界限为n,并返回一个具有新limit的缓冲区对象
Buffer mark()对缓冲区设置标记
int position()返回缓冲区的当前位置position
Buffer position(int n)将设置缓冲区的当前位置为n,并返回修改后的Buffer对象
int remaining()返回position和limit之间的元素个数
Buffer reset()将位置position转到以前设置的mark所在的位置
Buffer rewind()将位置设为为0,取消设置的mark

缓冲区的数据操作

Buffer 所有子类提供了两个用于数据操作的方法 get() 与 put() 方法

 获取 Buffer 中的数据
get() :读取单个字节
get(byte[] dst) :批量读取多个字节到 dst 中
get(int index) :读取指定索引位置的字节 ( 不会移动 position)
放入数据到 Buffer 中
put(byte b) :将给定单个字节写入缓冲区的当前位置
put(byte[] src) :将 src 中的字节写入缓冲区的当前位置
put(int index, byte b) :将指定字节写入缓冲区的索引位置 ( 不会移动 position)

package javaSEreview20190726.新IO的通道缓冲区的实现方式;

import java.nio.*;

/**
 * @Description:TODO
 * @Author:@李小白
 * @Date:2019/7/26 21:40
 */
public class Demo01channal和Buffer的方法 {
    public static void main(String[] args) {
//          通道:allocate
//        缓冲区:Buffer的底层是数组,他是用来存储数据的
//        除了boolean类型,其他的都有缓冲区
//        ByteBuffer
//        CharBuffer
//        IntBuffer
//        ShortBuffer
//        FloatBuffer
//        DoubleBuffer
//        LongBuffer
//        缓冲区的属性:Capacity容量
            //        limit界限之后都不读
            //        position指针,指针之后可读

        ByteBuffer allocate = ByteBuffer.allocate(10);//指定容量
        String str="1234567";
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------put-----------");
        allocate.put(str.getBytes());
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------flip-----------");
        allocate.flip();//切换速写模式,指针变动
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------get-----------");
        byte[] bytes = new byte[allocate.limit()];
        allocate.get(bytes);//获取
        System.out.println(new String(bytes,0,allocate.limit()));
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------rewid-----------");
        allocate.rewind();//重新获取
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------clear-----------");
        allocate.clear();//不清除数据,只是把指针和边界归位
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------mark-----------");
        byte[] bytes1 = new byte[allocate.limit()];
        allocate.get(bytes1,0,2);
        System.out.println(allocate.position());
        allocate.mark();//标记
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        System.out.println("----------------clear-----------");
        allocate.reset();//回到上次标记点
        System.out.println("容量"+allocate.capacity());
        System.out.println("指针"+allocate.position());
        System.out.println("边界"+allocate.limit());
        //判断是否还可以读取数据,还可以读取几个
        if (allocate.hasRemaining()) {
            System.out.println("还可以读取"+allocate.remaining()+"个");
        }
    }
}

通道(** Channel

通道( Channel ):由 java.nio.channels 包定义的。 Channel 表示 IO 源与目标打开的连接。
Channel 类似于传统的“流”。只不过 Channel本身不能直接访问数据, Channel 只能与Buffer 进行交互。!
Snipaste_2019-05-09_14-08-46.png

Snipaste_2019-05-09_14-12-00.png

Snipaste_2019-05-09_14-13-17.png

通道(** Channel

Java 为 Channel 接口提供的最主要实现类如下
本地文件传输通道
FileChannel :用于读取、写入、映射和操作文件的通道

网络数据传输的通道
DatagramChannel :通过 UDP 读写网络中的数据通道
SocketChannel :通过 TCP 读写网络中的数据。
ServerSocketChannel :可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel

获取通道

获取通道的一种方式是对支持通道的对象调用
getChannel() 方法。支持通道的类如下:
本地I/O
FileInputStream
FileOutputStream
RandomAccessFile

网络 I/O
DatagramSocket
Socket
ServerSocket

//缓冲区:非直接缓冲区,和直接缓冲区
        //非直接缓冲区:将缓冲区建立在JVM的内存中
        //直接缓冲区:将缓冲区建立在物理内存中

       // 非直接缓冲区allocate(1024)
         ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        //建立直接缓冲区allocateDirect(1024);
        ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(1024);

        //通道:
       // Channel
        //FileChannel 针对本地文件传输的通道
        //NIO 复制文件
        //获取通道
        //方式1.
       // FileOutputStream
       // FileInputStream
       // RandomAccessFile
       // getChannel();获取通道
        //方式2
        FileChannel inChannel = FileChannel.open(Paths.get("歌曲串烧.mp3"), StandardOpenOption.READ);
        FileChannel outChannl = FileChannel.open(Paths.get("歌曲串烧4.mp3"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

获取通道的其他方式是使用 Files 类的静态方法 newByteChannel() 获取字节通道。或者通过通道的静态方法 open() 打开并返回指定通道。
例如:
在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
//打开一个读取的通道
FileChannel in = FileChannel.open(Paths.get(“MyTest.java”), StandardOpenOption.READ);
//打开一个写的通道
FileChannel out = FileChannel.open(Paths.get(“MyTest.java”),StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()

以下是复制文件的方法

获非直接缓冲区取方式一:静态获取

package javaSEreview20190726.新IO的通道缓冲区的实现方式;

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

/**
 * @Description:TODO
 * @Author:@李小白
 * @Date:2019/7/26 22:14
 */
public class Demo01通道的获取非直接缓冲区方式1 {
    public static void main(String[] args) throws IOException {
        //封装两个流来放文件
        FileInputStream in = new FileInputStream("E:demo");
        FileOutputStream out = new FileOutputStream("E:\\demo2");
        //面向通道和缓冲区来获取文件
        //分配通道
        FileChannel inChannel = in.getChannel();//获取in缓冲区
        FileChannel outChannel = out.getChannel();//获取out缓冲区
        //分配非直接缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);//给一个内存空间
        //进行读写
        while (inChannel.read(byteBuffer)!=-1) {
            //切换读取模式
            byteBuffer.flip();
            //写数据
            outChannel.write(byteBuffer);
            //清空缓冲区
            byteBuffer.clear();
        }
        //释放资源
        in.close();
        out.close();
        inChannel.close();
        outChannel.close();



    }
}

获取非直接缓冲区方式二

package javaSEreview20190726.新IO的通道缓冲区的实现方式;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @Description:获取通道费直接缓冲区
 * @Author:@李小白
 * @Date:2019/7/26 22:27
 */
public class Demo03通道获取费直接缓冲区方式2 {
    public static void main(String[] args) throws IOException {
        //获取通道和输入地址
        //StandardOpenOption.CREATE_NEW 文件不存在就创建,存在就报错
        //StandardOpenOption.CREATE 文件不存在,就创建,存在 就覆盖
        FileChannel in = FileChannel.open(Paths.get("E:\\demo"), StandardOpenOption.READ);
        FileChannel out = FileChannel.open(Paths.get("E:\\demo02"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        //分配非直接缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 8);
        //进行读写
        while (in.read(byteBuffer)!=-1) {
            //切换读写模式,调整指针位置
            byteBuffer.flip();
            //写数据
            out.write(byteBuffer);
            //清空缓冲区
            byteBuffer.clear();
        }
        in.close();
        out.close();
    }
}

获取直接缓冲区方式三

package javaSEreview20190726.新IO的通道缓冲区的实现方式;

import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @Description:直接缓冲区方式三
 * @Author:@李小白
 * @Date:2019/7/26 22:36
 */
public class Demo03通道获取直接缓冲区方式3 {
    public static void main(String[] args) throws IOException {
        FileChannel in = FileChannel.open(Paths.get("E:\\demo"), StandardOpenOption.READ);
        FileChannel out = FileChannel.open(Paths.get("E:\\demo2"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        //建立直接缓冲区
        MappedByteBuffer inmap = in.map(FileChannel.MapMode.READ_ONLY,  0, in.size());
        MappedByteBuffer outmap = out.map(FileChannel.MapMode.READ_WRITE,  0, in.size());
        //数据读到缓冲区
        byte[] bytes = new byte[inmap.limit()];
        inmap.get(bytes);
        outmap.put(bytes);

        inmap.clear();
        outmap.clear();
    }
}

建立多个直接缓冲区四

分散 (Scatter)和聚集(Gather)

注意:按照缓冲区的顺序,从Channel中读取的数据依次将Buffer填满。
分散读取( Scattering Reads )是指从 Channel 中读取的数据“分散”到多个Buffer缓冲区中

聚集写入( Gathering Writes )是指将多个 Buffer缓冲区 中的数据“聚集”到 Channel 。

注意:按照缓冲区的顺序,写入position和limit之间的数据到Channel
Snipaste_2019-05-13_14-34-23.png

 FileChannel inChannel = FileChannel.open(Paths.get("作业处理.java"), StandardOpenOption.READ);

        FileChannel outChanle = FileChannel.open(Paths.get("作业处理2.java"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        //分配多个缓冲区
        ByteBuffer byteBuffer1 = ByteBuffer.allocate(100);
        ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024 * 2);
        //定义一个数组
        ByteBuffer[] byteBuffers={byteBuffer1,byteBuffer2};
        //把通道中的数据,放到多个buffer中
        inChannel.read(byteBuffers);
        //byteBuffers[0].flip();
        //byte[] array = byteBuffers[0].array();
        //String s = new String(array, 0, byteBuffers[0].limit());
        //System.out.println(s);
        //聚集
        for (ByteBuffer byteBuffer : byteBuffers) {
            byteBuffer.flip();//转换成读取模式
        }
        //写出数据
        outChanle.write(byteBuffers);
        //释放资源
        outChanle.close();
        inChannel.close();

建立直接缓冲区五

Path 与 Paths

  • java.nio.file.Path 接口代表一个平台无关的平台路径,描述了目录结构中文件的位置。

  • Paths 提供的get()方法用来获取Path对象

  • Path get(String first,String… more): 用于将多个字符串串连成路径

  • Path 常用方法

  • java.nio.file.Path 接口代表一个平台无关的平台路径,描述了目录结构中文件的位置。

  • Paths 提供的get()方法用来获取Path对象

  • Path get(String first,String… more): 用于将多个字符串串连成路径

  • Path 常用方法
    boolean endsWith(String path) : 判断是否以 path 路径结束
    boolean startsWith(String path) : 判断是否以 path 路径开始
    boolean isAbsolute() : 判断是否是绝对路径
    Path getFileName() : 返回与调用 Path 对象关联的文件名
    Path getName(int idx) : 返回的指定索引位置 idx 的路径名称
    int getNameCount() : 返回 Path 根目录后面元素的数量
    Path getParent() :返回 Path 对象包含整个路径,不包含 Path 对象指定的文件路径
    Path getRoot() :返回调用 Path 对象的根路径
    Path resolve(Path p) : 将相对路径解析为绝对路径
    Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
    String toString() : 返回调用 Path 对象的字符串表示形式
    Path copy(Path src, Path dest, CopyOption … how) : 文件的复制

     Path createDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录

     Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件

     void delete(Path path) : 删除一个文件

     Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置

     long size(Path path) : 返回 path 指定文件的大小

    static Path write(Path path, Iterable<? extends CharSequence> lines, OpenOption… options) 可以将List集合中的数据写到文件中

Files 常用方法:用于判断
boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
boolean isExecutable(Path path) : 判断是否是可执行文件
boolean isHidden(Path path) : 判断是否是隐藏文件
boolean isReadable(Path path) : 判断文件是否可读
boolean isWritable(Path path) : 判断文件是否可写
boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
public static A readAttributes(Path path,Class type,LinkOption…
options) : 获取与 path 指定的文件相关联的属性。
例子:
BasicFileAttributes att = Files.readAttributes(Paths.get(“歌曲串烧.mp3”), BasicFileAttributes.class);
//获取文件的属性
att.creationTime().toMillis();

        att.lastAccessTime().toMillis();

        att.lastModifiedTime().toMillis();

Files 常用方法:用于操作内容
SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录
InputStream newInputStream(Path path, OpenOption…how): 获取 InputStream 对象
OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象

package org.westos.demo3;

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @Author: ShenMouMou
 * @CreateTime: 2019-07-26 14:00
 * @Description:西部开源教育科技有限公司
 */
public class MyTest5 {
    public static void main(String[] args) throws IOException {
        //通道中的文件传输
        FileChannel inChannel = FileChannel.open(Paths.get("歌曲串烧.mp3"), StandardOpenOption.READ);

        FileChannel outChanle = FileChannel.open(Paths.get("歌曲串烧7.mp3"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        //站在输入通道的角度
        //inChannel.transferTo(0,inChannel.size(),outChanle);
        //站在输出通道的角度
        outChanle.transferFrom(inChannel,0,inChannel.size());

    }
}

建立直接缓冲区六


        //JDK1.7之后提供了一个工具类 Files newByteChannel()
        FileChannel in = (FileChannel) Files.newByteChannel(Paths.get("demo999.txt"), StandardOpenOption.READ);
        FileChannel out = (FileChannel) Files.newByteChannel(Paths.get("demo999.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

建立直接缓冲区七,最终

package javaSEreview20190726.新IO的通道缓冲区的实现方式;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

/**
 * @Description:TODO
 * @Author:@李小白
 * @Date:2019/7/26 22:57
 */
public class Demo05直接缓冲区方式7最终 {
    public static void main(String[] args) throws IOException {
        //复制文件,参1;源文件路径,参数2:目标文件路径
        //StandardCopyOption.REPLACE_EXISTING 可选参数,文件存在,就覆盖
        Files.copy(Paths.get("E:\\demo"),Paths.get("E:\\demo2"), StandardCopyOption.REPLACE_EXISTING);
        //不给第三个参数,文件存在就报错,也就是多次复制,就报错
        Files.copy(new FileInputStream("E:\\demo"),Paths.get("E:\\demo2"),StandardCopyOption.REPLACE_EXISTING);

        Files.copy(Paths.get("E:\\demo"),new FileOutputStream("E:\\demo2"));
        
        //文件剪切
        Files.copy(Paths.get("E:\\demo"),Paths.get("E:\\demo2"));



    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaSE(Java Standard Edition)是Java平台的标准版,提供了Java语言的核心库和基础功能。下面是一些JavaSE基础知识的介绍: 1. Java语言特性:Java是一种面向对象的编程语言,具有简单、可移植、安全、高性能等特点。它支持自动内存管理(垃圾回收)、异常处理、多线程等特性。 2. 数据类型:Java提供了基本数据类型(如整型、浮点型、字符型、布尔型)和引用数据类型(如类、接口、数组)。可以使用变量来存储和操作数据。 3. 控制流程:Java提供了条件语句(如if-else、switch)、循环语句(如for、while、do-while)和跳转语句(如break、continue)来控制程序的执行流程。 4. 类和对象:Java是一种面向对象的语言,所有的代码都必须定义在类中。类是对象的模板,对象是类的实例。可以使用类来创建对象,并通过对象调用类中的方法和访问类中的属性。 5. 继承和多态:Java支持继承机制,一个类可以继承另一个类的属性和方法。通过继承可以实现代码的重用和扩展。多态是指同一个方法在不同的对象上有不同的行为。可以通过方法重写和方法重载来实现多态。 6. 异常处理:Java提供了异常处理机制,可以捕获和处理程序中的异常。通过try-catch-finally语句块可以捕获异常并进行相应的处理,保证程序的稳定性和可靠性。 7. 输入输出:Java提供了丰富的输入输出功能,可以通过标准输入输出、文件操作、网络通信等方式进行数据的输入和输出。 8. 集合框架:Java提供了一套集合框架,包括List、Set、Map等接口和实现类,用于存储和操作数据集合。集合框架提供了高效的数据结构和算法,方便开发者进行数据处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值