java io nio (三)字符集转换 File类 SE7中Path、Files

五  字符集转换和乱码问题

 

      a) 文件都是按字节存储的,即使是使用字符流对文件进行写入,最终也会转换成字节

              进行存储。这时就需要将字符转换成字节,不同的字符集一般转换成的字节格式是

              不同的。看下面代码

		String str = "字符";
		byte[] utf8 = str.getBytes("utf-8");
		System.err.println(Arrays.toString(utf8));
		//输出:[-27, -83, -105, -25, -84, -90]
		
		byte[] gbk = str.getBytes("gbk");
		System.err.println(Arrays.toString(gbk));
		//输出:[-41, -42, -73, -5]

 

       b) 由上面的代码可以看出,UTF-8字符集中,一个汉字占了3个字节,GBK占了两个

               字节。所以如果用UTF-8转换的字节写入文件,用GBK读取是会出现乱码的情况。

               建议用什么字符集写入就用什么字符集读取 。

 

       c)  不同的字符集,一般所表示的字符是相同的,不同的是表示字符的字节。所以遇到

                乱码情况,可以先以存入时的字符集,进行读取。然后再以需要的字符集进行存入。

 

       d)  通过String实现字符集转换

		String str = "字符";
		//按utf-8字符集格式,将字符转换成字节
		byte[] utf8 = str.getBytes("utf-8");
		//按utf-8字符集格式,将字节转换成字符
		str = new String(utf8, "utf-8");
		
		//按gbk字符集格式,将字符转换成字节
		byte[] gbk = str.getBytes("gbk");
		//按gbk字符集格式,将字节转换成字符
		str =  new String(gbk, "gbk");
		
		System.out.println(str);//输出:字符

 

 

 

       e)  通过java.nio.Charset实现字符集转换,ByteBuffer和CharBuffer都是nio包中的类

                一般作为nio通道的缓存使用

		// 虚拟机中的可用字符集
		SortedMap<String, Charset> sort = Charset.availableCharsets();
		for (String charsetName : sort.keySet())
			System.err.println(charsetName);// 输出所有字符集名称

		// 查看虚拟机默认字符集,在虚拟机启动时默认字符集确定,通常取决于底层操作系统的语言环境和字符集。
		Charset charset = Charset.defaultCharset();
		System.err.println(charset);// 输出:GBK

		// 判断虚拟机字符集是否可用
		boolean boo = Charset.isSupported("GBK");
		System.err.println(boo);// 输出:true

		String str = "字符";
		// 注册一个字符集
		Charset gbk = Charset.forName("GBK");
		// 按gbk字符集格式,将字符转换成字节
		ByteBuffer bb = gbk.encode(str);
		// byte[] bytes = bb.array();
		// 按gbk字符集格式,将字节转换成字符
		CharBuffer cb = gbk.decode(bb);
		System.out.println(cb);// 输出:字符

		Charset utf8 = Charset.forName("utf-8");
		System.out.println(utf8.decode(utf8.encode(cb)));// 输出:字符

  

 

 

一 File类

 

    a)File.pathSeparator系统有关的默认路径分隔符 windows是;  unix是: 

    b)File.separator系统有关的默认名称分隔符 windows是\,unix是/

    c)mkdirs()方法可以创建路径中所有不存在的目录

	public static void main(String[] args) throws IOException {
		
		String path = "D:" + File.separator + "test.txt";
		File file = new File(path);

		// 文件如果不存在
		if (!file.exists()) {
			
			// 创建一个文件夹
			file.mkdir();
			
			// 删除一个文件/文件夹
			if (file.exists())
				file.delete();
			
			// 创建一个文件
			file.createNewFile();
		}
	}

   

    c) 文件/文件夹的名字、路径

	public static void main(String[] args) throws IOException {

		String path = "D:" + File.separator;
		File file = new File(path);

		// 判断file是否是文件夹
		if (file.isDirectory()) {

			// 返回当前目录下所有文件\文件夹名字
			String[] names = file.list();
			for (String name : names) {
				System.out.println(name);
			}

			// 返回当前目录下,每个文件\文件夹的File对象
			File[] files = file.listFiles();
			for (File elem : files) {//遍历名字、路径
				System.out.println(elem.getName());
				System.out.println(elem.getPath());
			}

		}

	}

    

    d) 递归目录中所有文件

public class IoTest {

	/**
	 * 递归当前目录下所有文件
	 */
	public static void filePrintln(File file) throws IOException {

		//遍历当前目录下所有项
		for (File f : file.listFiles())
			if (f.isDirectory()) //如果是一个目录
				filePrintln(f);// 递归
			else
				System.out.println(f.getPath());

	}

	public static void main(String[] args) throws IOException {

		String path = "D:" + File.separator ;
		IoTest.filePrintln(new File(path));

	}
}

  

    e) file.listFiles(filter)方法可以传一个FilenameFilter接口的实现类,这个接口只有一个方法

           accept(),提供该参数的目的是listFiles()会回调accept(),进而决定哪些文件是所需的。

     f)这是一个典型的策略模式,listFiles()可以根据FilenameFilter的不同实现类,进行文件

           的筛选。

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.regex.Pattern;

public class IoTest {
	
	public static class FileName implements FilenameFilter{
		private Pattern pattern;

		/**
		 * 构造器		
		 * @param regex 传入一个正则表达式,指定为一个字符串
		 */
		public FileName(String regex){
			//regex必须先编译成这个类的一个实例,由此可以产生一个匹配器,可以匹配任何字符序列
			this.pattern = Pattern.compile(regex);
		}
		
		@Override
		public boolean accept(File dir, String name) {
			//通过正则表示匹配器,对每个文件名name进行筛选是否符合条件
			return pattern.matcher(name).matches();
		}
		
	}



	public static void main(String[] args) throws IOException {
		
		String path = "D:" + File.separator ;
		File file = new File(path);
		//匹配小写字母命名的java文件
		File[] files  = file.listFiles(new IoTest.FileName("[a-z]+\\.[Jj]ava"));
		for(File f : files){
			System.out.println(f.getPath());
		}

	}
}

 

 

二 Paths类、Files类、Path接口

 

    a)以上的类或接口都是Java SE7中添加进来的,在java.nio.file包中

    b)Paths类只有两个方法,主要作用是生成Path对象

    c)Path对象跟其名字意义是一样的,只涉及对路径的操作

	public static void main(String[] args) throws IOException {

		String p = "D:" + File.separator + "file" + File.separator + "TEXT.txt";

		// 初始化一个Path对象
		Path path = Paths.get(p);
		
		//或者,功能等同于上面
		path = Paths.get("D:","file","TEXT.txt");
		
		//方法参数Paths.get(String first, String... more)

		// Path对象——>File对象
		File file = path.toFile();

		// File对象——>Path对象
		path = file.toPath();

		// 文件路径
		System.out.println(path);
		// 输出:D:\file\TEXT.txt

		// 文件名
		System.out.println(path.getFileName());
		// 输出:TEXT.txt

		// 父路径,没有时返回null
		System.out.println(path.getParent());
		// 输出:D:\file
		
		//跟路径
		System.out.println(path.getRoot());
		//输出:D:\
		
		//移除.和..等冗余的路径元素
		path.normalize();

		//创建一个同级的Path对象
		Path path2 = path.resolveSibling("TEXT2.txt");
		System.out.println(path2);
		//输出:D:\file\TEXT2.txt
		
		//可以在目录下创建文件Path对象
		Path path3 = path.resolve("TEXT2.txt");
		System.out.println(path3);
		//输出:D:\file\TEXT.txt\TEXT2.txt
	}

 

     d)Files只涉及对文件的操作,但是基本都是通过路径Path这个媒介

	public static void main(String[] args) throws IOException {

		// 初始化一个Path对象
		Path path = Paths.get("D:", "file", "TEXT.txt");

		// 文件是否存在,第二个参数貌似还没有什么实际意义
		Files.exists(path, LinkOption.NOFOLLOW_LINKS);

		// 是否目录
		Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS);

		// 按字节度量尺寸,只适用文件
		Files.size(path);

		//读取文件的属性,可以得到文件的创建、修改时间等
		BasicFileAttributes ba = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
		
		// 删除文件
		Files.deleteIfExists(path);

	}

 

     e)Files类可以很方便的处理中等长度的文本文件

	public static void main(String[] args) throws IOException {

		// 初始化一个Path对象
		Path path = Paths.get("D:", "file", "TEXT.txt");

		// 读取文件中所有内容
		byte[] bytes = Files.readAllBytes(path);

		// 按照行进行读入
		List<String> lines = Files.readAllLines(path, Charset.forName("GBK"));

		// 写入内容到文件,第二个参数貌似有问题,不太好用
		Files.write(path, "sss".getBytes(), StandardOpenOption.WRITE);

		// 在文件后面追加内容
		Files.write(path, "追加".getBytes(), StandardOpenOption.APPEND);

		// 复制字节输入流到文件
		Files.copy(System.in, path, StandardCopyOption.REPLACE_EXISTING);

		// 可以生成字节流、字符流
		InputStream in = Files.newInputStream(path, StandardOpenOption.READ);
		BufferedReader bf = Files.newBufferedReader(path, Charset.forName("GBK"));
	}

   

    f)通过Files创建目录或者文件不成功,记下以后解决

	public static void main(String[] args) throws IOException {

		// 初始化一个Path对象
		Path path = Paths.get("D:","file","TEXTa.txt");

		//创建新目录
		//文件属性集合
		Set<PosixFilePermission> set = EnumSet.allOf(PosixFilePermission.class);
		// 这里会抛错,貌似windows不支持posix
		Files.createDirectories(path, PosixFilePermissions.asFileAttribute(set));

		//创建一个文件,同上面一样执行无法通过
		Files.createFile(path, PosixFilePermissions.asFileAttribute(set));

	}

 

    g)Files可以很方便的复制文件

	public static void main(String[] args) throws IOException {

		// 初始化一个Path对象
		Path fromPath = Paths.get("D:","file","TEXT.txt");
		Path pathTo = Paths.get("D:","file","aaa","TEXT.txt");

		// 将文件从一个位置复制到另一个位置
		Files.copy(fromPath, pathTo, StandardCopyOption.REPLACE_EXISTING);
		
		//复制并删除源文件
		Files.move(fromPath, pathTo, StandardCopyOption.REPLACE_EXISTING);
		
		//REPLACE_EXISTING 取代现有文件
		//COPY_ATTRIBUTES复制所有文件属性
		//ATOMIC_MOVE 操作原子性,成功||什么都没做
		
		
	}

 

 

    h)Files 对文件进行遍历,在遍历所有目录及其子目录时功能很强大     

	public static void main(String[] args) throws IOException {

		// 初始化一个Path对象
		Path path = Paths.get("D:", "file");

		// 得到当前目录下所有文件路径。这种try的写法,1.7中新功能,可以自动关闭流
		try(DirectoryStream<Path> dir = Files.newDirectoryStream(path)){
			for (Path entry : dir) 
				System.out.println(entry);
			
		}

		// 通过glob模式对文件进行过滤
		DirectoryStream<Path> dirGlob = Files.newDirectoryStream(path, "*.java");

		// 遍历所有目录及其子目录,后台也是通过递归来实现
		Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
			@Override
			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
				// 输出所有文件路径
				System.out.println(file);
				return super.visitFile(file, attrs);
			}

			@Override
			public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
				// 输出所有目录路径
				System.out.println(dir);
				return super.preVisitDirectory(dir, attrs);
			}
		});
	}

 

    讲解一下上面的最后一个方法 

	 //其中第二个参数FileVisitor有四个方法
	 //方法1:在遇到文件时调用(非目录)
	 FileVisitResult visitFile(T file, BasicFileAttributes attrs)
	 //方法2:在处理一个目录之前调用
	 FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
	 // 方法3:在处理一个目录之后调用
	 FileVisitResult postVisitDirectory(T dir, IOException exc)
	 //方法4:在试图处理一个文件或目录时发生错误,例如没有权限打开目录
	 FileVisitResult visitFileFailed(T file, IOException exc)
	
	 //在执行上面4个步骤时,都会返回FileVisitResult对象,可以指定是否希望执行下面的操作
	 //1:继续访问下一个文件
	 FileVisitResult.CONTINUE
	 //2:继续访问,但是不访问这个目录下的任何项
	 FileVisitResult.SKIP_SIBLINGS
	 //3:终止访问
	 FileVisitResult.TERMINATE

 

 

         

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值