缓冲区Files.copy()"/>
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 的区别
IO | NIO |
---|---|
面向流(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 进行交互。!
通道(** 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();获取通道//方式2FileChannel 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
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"));}
}
更多推荐
javaSE基础知识——day16 新IO流,通道和缓冲区Files.copy()
发布评论