1.NIO与IO的比较
IO NIO
面向流 面向缓冲区
是阻塞式的 有非阻塞式的
没有选择器 有selector选择器
2.NIO的主要组件
channels selector buffer
3.NIO2的主要更新内容
Path Files Paths
4.Buffer的几个重要属性
capacity 最大的空间值
limit 可操作的最大数据
position 指向当前的操作数,保存的是下标
mark 修改当前的操作下标
工作:数据从文件--(通过通道实现)--内存中的buffer--传到新文件/控制台等
5.几个重要方法
allocate 开辟空间
put 向buffer读入数据
flip 读写切换
get 取出buffer的数据
rewind 将position的值归零
clear 返回开辟时的状态
6.读模式和写模式
读模式-写模式:flip() 从缓冲区取出数据 capacity:最大值 limit:可操作的最大值 position:0
写模式-读模式:clear() 将数据写入缓冲区 capacity:最大值 limit:capacity position:可操作的最大值
案例:
1.使用NIO将桌面的hello.txt目录拷贝到桌面的woshow中起名myhello.txt
2.使用NIO将数据放入List<Person>
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
/*
分析:
IO流
集合
面向对象--模型
NIO
*/
public class test {
public static void main(String[] args) throws IOException {
//1.使用NIO将桌面的hello.txt目录拷贝到桌面的woshow中起名myhello.txt
copyDir1("C:\\Desktop\\hello.txt","C:\\Desktop\\woshow\\myhello.txt");
//2.使用NIO将数据放入List<Person>
List<Preson> list = getData2("C:\\Desktop\\woshow\\myhello.txt");
System.out.println("list"+list);
}
//1.使用NIO将桌面的hello.txt目录拷贝到桌面的woshow中起名myhello.txt
//第一种方式:使用Files方法
public static void copyDir1(String src,String dst){
//创建目录
creatPath();
try {
Files.copy(Paths.get(src),Paths.get(dst));
} catch (IOException e) {
e.printStackTrace();
}
}
//第二种方式:使用NIO的通道(channel+缓冲区(buffer))--通过流获取通道
//拷贝的东西多时可以看到好处
public static void copyDir2(String src,String dst){
//创建目录
creatPath();
//创建字节输入流
//InputStream没有getChannel方法
try (FileInputStream inputStream = new FileInputStream(src);
FileOutputStream outputStream = new FileOutputStream(dst)){
//输入通道--将数据放入内存
FileChannel inChannel=inputStream.getChannel();
//输出通道--将数据放入文件(磁盘)
FileChannel outChannel=outputStream.getChannel();
//创建缓冲区
ByteBuffer byteBuffer=ByteBuffer.allocate(10);
//执行读写
int num=0;
while((num=inChannel.read(byteBuffer))!=-1) {
//从写模式切换到读模式
byteBuffer.flip();
//将数据从bytebuffer读出,写入到dst
outChannel.write(byteBuffer);
//重新切换成写模式
//注意:缓冲区的数据并没有清空,只是回到了初始状态,postition=0 limit=10
byteBuffer.clear();
}
//创建字节输出流
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//第三种方式:使用NIO的通道(channel+缓冲区(buffer))--通过Feils的open方法获取通道
public static void copyDir3(String src,String dst){
//创建目录
creatPath();
//创建字节输入流
//InputStream没有getChannel方法
try {
//输入通道--将数据放入内存
FileChannel inChannel=FileChannel.open(Paths.get(src),StandardOpenOption.READ);
//输出通道--将数据放入文件(磁盘)
FileChannel outChannel=FileChannel.open(Paths.get(src),StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//创建缓冲区
ByteBuffer byteBuffer=ByteBuffer.allocate(10);
//执行读写
int num=0;
while((num=inChannel.read(byteBuffer))!=-1) {
//从写模式切换到读模式
byteBuffer.flip();
//将数据从bytebuffer读出,写入到dst
outChannel.write(byteBuffer);
//重新切换成写模式
//注意:缓冲区的数据并没有清空,只是回到了初始状态,postition=0 limit=10
byteBuffer.clear();
}
//创建字节输出流
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建目录
public static void creatPath() {
Path path=Paths.get("C:\\Users\\兰翎\\Desktop\\woshow");
try {
if (!Files.exists(path)){
Files.createDirectories(path);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//2.使用NIO将数据放入List<Person>
//第一种:直接使用Channel+buffer
/*
IO流
输入流
通道:输入通道
StandardOpenOption---READ
输出流
通道:输出通道
StandardOpenOption--WRITE
*/
public static List<Preson> getData1(String src){
List<Preson> list=new ArrayList<>();
try(FileChannel inChannel=FileChannel.open(Paths.get(src), StandardOpenOption.READ)){
//创建缓冲区
ByteBuffer byteBuffer=ByteBuffer.allocate(10);
//读数据
int num=0;
StringBuffer stringBuffer=new StringBuffer();
while((num=inChannel.read(byteBuffer))!=-1){
//切换写模式
byteBuffer.flip();
byte[] arr=new byte[byteBuffer.limit()];
byteBuffer.get(arr);
String str=new String(arr);
//切回写模式
byteBuffer.clear();
}
System.out.println("stringBuffer:"+stringBuffer);
//再对可变字符串进行切割
String[] lines = stringBuffer.toString().split("\n");
for (String line : lines) {
list.add(new Preson(line));
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
//第二种:使用Files方法:readAllLines
public static List<Preson> getData2(String src){
List<Preson> list1=null;
try {
//当前的集合中每一个元素就是一行数据
List<String> list= Files.readAllLines(Paths.get(src));
list1 = new ArrayList<>();
for (String s:list){
list1.add(new Preson(s));
}
} catch (IOException e) {
e.printStackTrace();
}
return list1;
}
//创建Person对象
static enum Gender {
Male, FeMale
}
static class Preson implements Serializable{
private static final long serialVersionUID=-123453465643445L;
private String name;
private int age;
Gender gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public Preson(String name, int age, Gender gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Preson{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
public Preson(String str) {
//切第一刀:;
String[] strs = str.split(";");
for (String string : strs) {
String[] pair = string.split(":");
//去空格
String key = pair[0].trim();
String value = pair[1].trim();
//正则表达式
if (key.equals("name")) {
this.name = value;
} else if (key.equals("age")) {
this.age = Integer.parseInt(value);
} else if (key.equals("sex")) {
if (value.equals("Male")){
this.gender=Gender.Male;
}else {
this.gender=Gender.FeMale;
}
}
}
}
}
}