Java NIO.2

Java NIO.2的主要表现为增加了Files、Path、Paths等功能类和基于异步Channel的IO。

1、Path、Paths

  如下为使用Path和工具类Paths的示例:

import java.io.*;
import java.net.*;
import java.nio.file.*;

public class Test
{
	public static void main(String[] args)
		throws Exception
	{
		// 以当前路径来创建Path对象
		Path path = Paths.get(".");
		
		// 获取path对应的绝对路径。
		Path absolutePath = path.toAbsolutePath();
		System.out.println(absolutePath); // “D:\java_project\Test\sources\.”
		
		// 获取绝对路径的根路径
		System.out.println("absolutePath的根路径:" + absolutePath.getRoot()); // “D:\”
		
		// 获取绝对路径所包含的路径数量
		int iCnt = absolutePath.getNameCount();
		System.out.println("absolutePath里包含的路径数量:" + iCnt); // 4
		for(int i = 0; i < iCnt; ++i)
			System.out.println(absolutePath.getName(i));// “java_project”、“Test”、“sources”、“.”
		
		// 以多个String来构建Path对象
		Path path2 = Paths.get("g:" , "publish" , "codes");
		System.out.println(path2); //“g:\publish\codes”


        Path p1 = Paths.get("C:\\workspace");
		Path p2 = Paths.get("Desktop\\books");
		Path p3 = Paths.get(System.getProperty("user.home"), "Documents", "Downloads"); //获得用户目录下的Documents\Downloads目录
		String str = p3.toString(); // "C:\Users\Administrator\Documents\Downloads"
		p3.forEach(System.out::println); //Users,Administrator,Documents,Downloads
		str = "" + p3.getFileName(); // "Downloads"
		int n = p3.getNameCount(); //4
		str = "" + p1.resolve(p3.getName(0)); //"C:\workspace\Users"
		str = "" + p3.subpath(0,  2); //"Users\\Administrator"
		str = "" + p3.getRoot(); //"C:\"
	}
}

  使用Path的register()可以监听该Path代表的目录下文件的变化。

2、BasicFileAttributes

import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;

public class Test
{
	
	public static void main(String[] args) throws IOException
	{
        //获得目录的属性
		Path path = Paths.get("C:\\Windows");
		BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); //获得目录的所有属性
		String str = "" + attrs.lastModifiedTime(); //上次修改时间,也可以直接通过Files.getLastModifiedTime()来获取
		boolean b = attrs.isDirectory(); //是否是目录
		b = attrs.isSymbolicLink(); //是否是符号链接
		long size = attrs.size(); //大小
		
		int uid = (Integer)Files.getAttribute(path, "unix:uid"); //获得指定属性

        //获得文件的属性
		Path path2 = Paths.get("C:\\Windows\\bootstat.dat");
		attrs = Files.readAttributes(path2, BasicFileAttributes.class); //获得目录的所有属性
		size = attrs.size();

        //获得根目录路径
		Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();
		dirs.forEach(System.out::println); //输出 C:\,D:\,E:\,F:\
		
		//获得各个盘的容量和使用情况
		FileSystem fs = FileSystems.getDefault();
		for(FileStore store:fs.getFileStores())
		{
			long total = store.getTotalSpace(); //总容量
			long used = total - store.getUnallocatedSpace(); //已用空间
			long usable = store.getUsableSpace(); //可用空间
			
			System.out.println(String.format("%s, %dG, %dG, %dG", store.toString(), total / 1024 / 1024 / 1024, used / 1024 / 1024 / 1024, usable / 1024 / 1024 / 1024));
		}
		 
		
	}
}

3、Files

  Files是File对应的工具类,通过它不仅可以直接获得文件大小、复制文件等,它还可以直接来读取文件、写入文件, 以下为使用工具类Files的示例:

import java.nio.file.*;
import java.nio.charset.*;
import java.io.*;
import java.util.*;

public class FilesTest
{
	public static void main(String[] args)
		throws Exception
	{
        //判断文件是否存在
        boolean b = Files.exists(Paths.get("FilesTest.java"));

        //是否是目录
        b = Files.isDirectory(Paths.get("FilesTest.java"));

		// 复制文件
		Files.copy(Paths.get("FilesTest.java"), new FileOutputStream("a.txt"));
        Files.copy(Paths.get("D:\\TestU.java"), Paths.get("E:\\TestU.java"), StandardCopyOption.REPLACE_EXISTING); //复制文件,已存在则覆盖

        //移动文件
        Files.move(...);

        //建立目录,
        Files.createDirectory(); //如果父目录不存在会抛出异常
        Files.createDirectories(); //如果父目录不存在则创建
        
		
		//删除文件或目录
		Path path = Paths.get("D:\\TestU.java");
		Files.delete(path); //文件不存在或目录不为空会抛出异常
		Files.deleteIfExists(path); //文件不存在不会抛出异常
		
		// 判断FilesTest.java文件是否为隐藏文件/可执行文件
		System.out.println("FilesTest.java是否为隐藏文件:" + Files.isHidden/*isExecutable*/(Paths.get("FilesTest.java")));
		
        //一次性读取文件的所有数据
        byte[] ary = Files.readAllBytes();

		// 一次性读取字符文件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新增的管线化(流式操作)列出当前目录下所有文件和子目录
        // Files.list()列出当前的文件和目录,Files.walk()还会递归列出子目录中的文件
		Files.list(Paths.get(".")).forEach(path -> System.out.println(path));
		// 使用Java 8新增的Stream读取文件中每行内容
		Files.lines(Paths.get("FilesTest.java") , Charset.forName("gbk")).forEach(line -> System.out.println(line));
		
		// 获得C盘的总空间,可用空间
		FileStore cStore = Files.getFileStore(Paths.get("C:"));
		System.out.println("C:共有空间:" + cStore.getTotalSpace());
		System.out.println("C:可用空间:" + cStore.getUsableSpace());
	}
}

  除了使用Files的list()外,还有传统的遍历目录的方法,如下所示,Files.newDirectoryStream()的第二个参数可以指定Glob比较范例来设置过滤的文件,如"*.{class, jar}"表示只获得.class或.jar文件,其它的Glob范例如下所示,如果Glob范例无法满足需求的话可以使用DirectoryStream.Filter接口的操作对象,操作其accept()方法来自行定义过滤条件,该方法返回true表示符合过滤条件。

import java.nio.file.*;
import java.io.IOException;
import java.util.*;

public class Test
{
	public static void main(String[] args) throws IOException
	{
		//遍历D盘,先输出目录名再输出文件名
		try(DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get("D:\\")/*, "*.{class, jar}"*/))
		{
			List<String> files = new ArrayList<>();
			for(Path path : directoryStream)
			{
				if(Files.isDirectory(path))
					System.out.println(path.getFileName());
				else
					files.add(path.getFileName().toString());
			}
			files.forEach(System.out::println);
		}
	}
}

 

 

  使用Files的walkFileTree()方法遍历文件和目录会更加方便,它还可以指定遍历的深度,递归进行遍历,其参数类型FileVisitor代表一个文件访问器接口,当遍历的时候会触发其中相应的方法,必须实现这四个方法:

   preVisitDirectory()为访问子目录之前触发。
   postVisitDirectory()为访问子目录之后触发。
   visitFile()为访问文件时触发。
   visitFileFailed为访问文件失败时触发。

  上面这些方法都返回一个FileVisitResult对象,它是一个枚举类对象,用来定义后续行为:

   CONTINUE:继续访问。
   SKIP_SIBLINGS:不访问兄弟文件或目录。
   SKIP_SUBTREE:不访问子目录树。
   TERMINATE:终止访问。

  如下为使用Files的walkFileTree()方法遍历指定目录的示例:


import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;

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;
			}
		});
	}
}

  java.nio.file.attribute包下提供了XxxAttributeView工具类可以查看或设置文件的修改时间、访问时间、是否只读、是否为系统文件、所有者权限、组所有者等。

4、异步IO

   AsynchronousChannel的实现类AsynchronousFileChannel、AsynchronousSocketChannel、AsynchronousServerSocketChannel用来进行异步IO,具体的实现可以参考Java网络编程(2):TCP和UDP里AIO部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值