NIO
- channel:可以理解为一个通道。channel把文件中数据映射到Buffer中。然后channel操作Buffer进行读写操作
- Buffer: 就是一个容器,channel进行读写的容器工具,另外,Buffer本身也可以完成读写操作
使用Buffer
- 从0开始就有数据
- capacity:容量。
- limit:第一个不应该被操作的缓冲区索引位置。limit之后不可读写
- position: 当前可操作的位置。大小是已经读到数据大小
- mark:自游标,可以把position置为mark
- 创建Buffer后position初始值为0,limit为capacity
- 在Buffer中每读取一个数据,position+1.
- flip():读取数据完成以后,调用 flip()方法,position变为0,limit变为position。调用 flip()方法为输出数据做好准备(封闭包)
- clear():该方法不会清空缓冲区,只将position变为0,limit变为capacity。为再次输入做好准备
-
put()和get()方法
-
相对操作: Buffer从position的位置进行读写 position+1 get();
-
绝对操作:Buffer使用索引位置进行读写 ,根据索引操作不会影响position的位置 get(int x);
使用Channel
- 程序只能通过Buffe与Channel交换数据
- 常用方法:map() read() write()系列方法
- 获取方法: 节点流.getChannel();
- 实例复制文件内容到a.txt 并打印内容(映射整个文件)
-
public class FileChannelTest { public static void main(String[] args) { File f = new File("FileChannelTest.java"); try( // 创建FileInputStream,以该文件输入流创建FileChannel FileChannel inChannel = new FileInputStream(f).getChannel(); // 以文件输出流创建FileBuffer,用以控制输出 FileChannel outChannel = new FileOutputStream("a.txt") .getChannel()) { // 将FileChannel里的全部数据映射成ByteBuffer MappedByteBuffer buffer = inChannel.map(FileChannel .MapMode.READ_ONLY , 0 , f.length()); // ① // 使用GBK的字符集来创建解码器 Charset charset = Charset.forName("GBK"); // 直接将buffer里的数据全部输出 outChannel.write(buffer); // ② // 再次调用buffer的clear()方法,复原limit、position的位置 buffer.clear(); // 创建解码器(CharsetDecoder)对象 CharsetDecoder decoder = charset.newDecoder(); // 使用解码器将ByteBuffer转换成CharBuffer CharBuffer charBuffer = decoder.decode(buffer); // CharBuffer的toString方法可以获取对应的字符串 System.out.println(charBuffer); } catch (IOException ex) { ex.printStackTrace(); } } }
- 复制a.txt文件内容追加到a.txt末尾(使用RandomAccessFile对象获取Channel)
-
public class RandomFileChannelTest { public static void main(String[] args) throws IOException { File f = new File("a.txt"); try( // 创建一个RandomAccessFile对象 RandomAccessFile raf = new RandomAccessFile(f, "rw"); // 获取RandomAccessFile对应的Channel FileChannel randomChannel = raf.getChannel()) { // 将Channel中所有数据映射成ByteBuffer ByteBuffer buffer = randomChannel.map(FileChannel .MapMode.READ_ONLY, 0 , f.length()); // 把Channel的记录指针移动到最后 randomChannel.position(f.length()); // 将buffer中所有数据输出 randomChannel.write(buffer); } } }
映射文件的一部分,(每次取一部分)
-
public class ReadFile { public static void main(String[] args) throws IOException { try( // 创建文件输入流 FileInputStream fis = new FileInputStream("ReadFile.java"); // 创建一个FileChannel FileChannel fcin = fis.getChannel()) { // 定义一个ByteBuffer对象,用于重复取水 ByteBuffer bbuff = ByteBuffer.allocate(256); // 将FileChannel中数据放入ByteBuffer中 while( fcin.read(bbuff) != -1 ) { // 锁定Buffer的空白区 bbuff.flip(); // 创建Charset对象 Charset charset = Charset.forName("GBK"); // 创建解码器(CharsetDecoder)对象 CharsetDecoder decoder = charset.newDecoder(); // 将ByteBuffer的内容转码 CharBuffer cbuff = decoder.decode(bbuff); System.out.print(cbuff); // 将Buffer初始化,为下一次读取数据做准备 bbuff.clear(); } } } }
字符集与和Charset
- 没啥东西贴个代码好了
-
public class CharsetTest { public static void main(String[] args) { // 获取Java支持的全部字符集 SortedMap<String,Charset> map = Charset.availableCharsets(); for (String alias : map.keySet()) { // 输出字符集的别名和对应的Charset对象 System.out.println(alias + "----->" + map.get(alias)); } } }
public class CharsetTransform { public static void main(String[] args) throws Exception { // 创建简体中文对应的Charset Charset cn = Charset.forName("GBK"); // 获取cn对象对应的编码器和解码器 CharsetEncoder cnEncoder = cn.newEncoder(); CharsetDecoder cnDecoder = cn.newDecoder(); // 创建一个CharBuffer对象 CharBuffer cbuff = CharBuffer.allocate(8); cbuff.put('孙'); cbuff.put('悟'); cbuff.put('空'); cbuff.flip(); // 将CharBuffer中的字符序列转换成字节序列 ByteBuffer bbuff = cnEncoder.encode(cbuff); // 循环访问ByteBuffer中的每个字节 for (int i = 0; i < bbuff.capacity() ; i++) { System.out.print(bbuff.get(i) + " "); } // 将ByteBuffer的数据解码成字符序列 System.out.println("\n" + cnDecoder.decode(bbuff)); } }
可以不获取CharsetEncoder对象,Charset对象可以直接进行编码或解码
文件锁
- lock();阻塞式,若无法得到锁,将会阻塞线程
- trylock():非阻塞式,若无法得到锁,返回null
-
public class FileLockTest { public static void main(String[] args) throws Exception { try( // 使用FileOutputStream获取FileChannel FileChannel channel = new FileOutputStream("a.txt") .getChannel()) { // 使用非阻塞式对指定文件加锁 FileLock lock = channel.tryLock(); // 暂停10s Thread.sleep(10000); // 释放锁 lock.release(); } } }
NIO2
- 核心API: Path Paths(工具) Files (工具)
- path使用
-
public class PathTest { public static void main(String[] args) throws Exception { // 以当前路径来创建Path对象 Path path = Paths.get("."); System.out.println("path里包含的路径数量:" + path.getNameCount()); System.out.println("path的根路径:" + path.getRoot()); // 获取path对应的绝对路径。 Path absolutePath = path.toAbsolutePath(); System.out.println(absolutePath); // 获取绝对路径的根路径 System.out.println("absolutePath的根路径:" + absolutePath.getRoot()); // 获取绝对路径所包含的路径数量 System.out.println("absolutePath里包含的路径数量:" + absolutePath.getNameCount()); System.out.println(absolutePath.getName(3)); // 以多个String来构建Path对象 Path path2 = Paths.get("g:" , "publish" , "codes"); System.out.println(path2); } }
Files使用
-
public class FilesTest { public static void main(String[] args) throws Exception { // 复制文件 Files.copy(Paths.get("FilesTest.java") , new FileOutputStream("a.txt")); // 判断FilesTest.java文件是否为隐藏文件 System.out.println("FilesTest.java是否为隐藏文件:" + Files.isHidden(Paths.get("FilesTest.java"))); // 一次性读取FilesTest.java文件的所有行 List<String> lines = Files.readAllLines(Paths .get("FilesTest.java"), Charset.forName("gbk")); System.out.println(lines); // 判断指定文件的大小 System.out.println("FilesTest.java的大小为:" + Files.size(Paths.get("FilesTest.java"))); List<String> poem = new ArrayList<>(); poem.add("水晶潭底银鱼跃"); poem.add("清徐风中碧竿横"); // 直接将多个字符串内容写入指定文件中 Files.write(Paths.get("pome.txt") , poem , Charset.forName("gbk")); // 使用Java 8新增的Stream API列出当前目录下所有文件和子目录 Files.list(Paths.get(".")).forEach(path -> System.out.println(path)); // 使用Java 8新增的Stream API读取文件内容 Files.lines(Paths.get("FilesTest.java") , Charset.forName("gbk")) .forEach(line -> System.out.println(line)); FileStore cStore = Files.getFileStore(Paths.get("C:")); // 判断C盘的总空间,可用空间 System.out.println("C:共有空间:" + cStore.getTotalSpace()); System.out.println("C:可用空间:" + cStore.getUsableSpace()); } }
FileVistor遍历文件和目录
- Files.walkFileTree(path ,FileVistor )
- FileVistor的四个方法
- FileVisitResult postVisitDirectory(): 访问目录以后触发
- FileVisitResultpre VisitDirectory():访问前
- FileVisitResult visitFile():访问文件时触发
- FileVisitResult visitFileFaied():失败触发
- FileVisitResult 枚举类,描述以后的行为
-
public class FileVisitorTest { public static void main(String[] args) throws Exception { / 遍历g:\publish\codes\15目录下的所有文件和子目录 Files.walkFileTree(Paths.get("g:", "publish" , "codes" , "15") , new SimpleFileVisitor<Path>() { / 访问文件时候触发该方法 @Override public FileVisitResult visitFile(Path file , BasicFileAttributes attrs) throws IOException { System.out.println("正在访问" + file + "文件"); / 找到了FileInputStreamTest.java文件 if (file.endsWith("FileInputStreamTest.java")) { System.out.println("--已经找到目标文件--"); return FileVisitResult.TERMINATE; } return FileVisitResult.CONTINUE; } / 开始访问目录时触发该方法 @Override public FileVisitResult preVisitDirectory(Path dir , BasicFileAttributes attrs) throws IOException { System.out.println("正在访问:" + dir + " 路径"); return FileVisitResult.CONTINUE; } }); } }
访问文件属性
-
public class AttributeViewTest { public static void main(String[] args) throws Exception { // 获取将要操作的文件 Path testPath = Paths.get("AttributeViewTest.java"); // 获取访问基本属性的BasicFileAttributeView BasicFileAttributeView basicView = Files.getFileAttributeView( testPath , BasicFileAttributeView.class); // 获取访问基本属性的BasicFileAttributes BasicFileAttributes basicAttribs = basicView.readAttributes(); // 访问文件的基本属性 System.out.println("创建时间:" + new Date(basicAttribs .creationTime().toMillis())); System.out.println("最后访问时间:" + new Date(basicAttribs .lastAccessTime().toMillis())); System.out.println("最后修改时间:" + new Date(basicAttribs .lastModifiedTime().toMillis())); System.out.println("文件大小:" + basicAttribs.size()); // 获取访问文件属主信息的FileOwnerAttributeView FileOwnerAttributeView ownerView = Files.getFileAttributeView( testPath, FileOwnerAttributeView.class); // 获取该文件所属的用户 System.out.println(ownerView.getOwner()); // 获取系统中guest对应的用户 UserPrincipal user = FileSystems.getDefault() .getUserPrincipalLookupService() .lookupPrincipalByName("guest"); // 修改用户 ownerView.setOwner(user); // 获取访问自定义属性的FileOwnerAttributeView UserDefinedFileAttributeView userView = Files.getFileAttributeView( testPath, UserDefinedFileAttributeView.class); List<String> attrNames = userView.list(); // 遍历所有的自定义属性 for (String name : attrNames) { ByteBuffer buf = ByteBuffer.allocate(userView.size(name)); userView.read(name, buf); buf.flip(); String value = Charset.defaultCharset().decode(buf).toString(); System.out.println(name + "--->" + value) ; } // 添加一个自定义属性 userView.write("发行者", Charset.defaultCharset() .encode("疯狂Java联盟")); // 获取访问DOS属性的DosFileAttributeView DosFileAttributeView dosView = Files.getFileAttributeView(testPath , DosFileAttributeView.class); // 将文件设置隐藏、只读 dosView.setHidden(true); dosView.setReadOnly(true); } }
-
关于文件监听 WatchService 和文件属性Attribute百度