Java基础——IO(二)——File类、Properties类、打印流、序列流(合并流)

第一讲 File类

一、概述

1、File类是文件和目录路径的抽象表现形式;

2、用来将文件或文件夹封装成对象;

3、File 类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变;

4、File类的对象可以作为参数传递给流的构造函数;

5、文件系统可以实现对实际文件系统对象上的某些操作(比如,读、写、执行)进行限制。


二、File对象创建

方式一:通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。这里给定的路径可以是存在的,也可以是不存在的。

        File file = new File("E:/demo.txt");
方式二:根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

        File file = new File("E:/", "demo.txt");
方式三:根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。降低了文件与父目录的关联性。
        File parentFile = new File("E:/");
        File parentFile = new File(parentFile, "demo.txt");
备注: File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。


三、File类的常见方法

1、创建

      当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。创建新文件后返回true,否则返回false。这和流不一样,流对象在初始化时就创建文件,并且如果文件已存在,会覆盖。

      public boolean createNewFile()

      创建此抽象路径名指定的目录(文件夹),并且只能创建一级目录的文件夹。

      public boolean mkdirs()

      创建此抽象路径名指定的目录,包括所有必需但不存在的父目录(创建多级目录的文件夹)。

      public boolean mkdirs()

2、删除

      删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。文件存在且操作成功返回true,文件不存在或正在被执行,返回false。

      public boolean delete()

      在虚拟机终止(程序退出)时,请求删除此抽象路径名表示的文件或目录。只有在虚拟机正常终止时,才会尝试执行删除操作。一旦请求了删除操作,就无法取消该请求。所以应小心使用此方法。

      public void deleteOnExit()

3、判断

      public boolean canExecute()// 测试应用程序是否可以执行此抽象路径名表示的文件(是否是可执行文件)。

      public boolean exists()// 测试此抽象路径名表示的文件或目录是否存在(文件是否存在)。

      public boolean isFile()// 当且仅当此抽象路径名表示的文件存在 是一个标准文件时,返回 true;否则返回 false。(是否是文件)

      public boolean isDirectory()// 测试此抽象路径名表示的文件是否是一个目录。(是否是文件夹)

      public boolean isHidden()// 测试此抽象路径名指定的文件是否是一个隐藏文件。

      public boolean isAbsolute()// 测试此抽象路径名是否为绝对路径名。

      备注:在判断文件对象是否是文件或者目录时,必须要判断该文件对象封装的内容是否存在。通过exists判断。

4、获取信息

      public String getName()// 返回由此抽象路径名表示的文件或目录的名称。
      public String getPath()// 将此抽象路径名转换为一个路径名字符串。此抽象路径名的字符串形式
      public String getParent()// 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
      public File getParentFile()// 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。
      public String getAbsolutePath()// 返回此抽象路径名的绝对路径名字符串。
      public long lastModified()// 返回此抽象路径名表示的文件最后一次被修改的时间。
      public long length()// 返回由此抽象路径名表示的文件的长度。如果此路径名表示一个目录,则返回值是不确定的。

5、列出文件及文件过滤

      public static File[] listRoots()// 列出可用的文件系统根。即系统盘符
      public String[] list()// 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
      public String[] list(FilenameFilter filter)// 返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。
      FilenameFilter:文件名过滤器,是一个接口,其中包含一个方法,accept(Filedir,String name),返回的是boolean型,对不符合条件的文件过滤掉。
      public File[] listFiles()// 返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹
      public File[] listFiles(FileFilter filter)// 返回抽象路径名数组,获取目录中满足指定过滤器的文件或目录。

使用示例:

package com.dawndaybreak.ioexample;

import java.io.File;
import java.io.FilenameFilter;

/**
 * 获取指定类型(后缀)的文件
 * 
 * @author dawn
 * 
 */
public class GetAppointFile {

	public static void main(String[] args) {
		String suffix = ".doc";
		String filePath = "E:\\project";
		String[] filenames = getAppointFile(filePath, suffix);
		for (String filename : filenames) {
			System.out.println(filename);
		}
	}

	/**
	 * 获取一个目录下所有指定后缀的文件,如果是文件夹则需要递归处理
	 * 
	 * @param filePath
	 *            指定目录
	 * @param suffix
	 *            指定后缀
	 * @return
	 */
	private static String[] getAppointFile(String filePath, final String suffix) {
		File file = new File(filePath);
		// 以内部类的形式实现FilenameFilter,并重写accept方法
		String[] filenames = file.list(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {
				return name.endsWith(suffix);
			}
		});
		return filenames;
	}
}

四、递归

1、递归定义

      当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。这种表现形式,或者编程手法,称为递归。
2、递归注事事项
      1)限定条件:用来解释循环调用,否则将会形成死循环。
      2)注意递归次数,尽量避免内存溢出。因为每次调用自身的时候都会先执行下一次调用自己的方法,所以会不断在栈内存中开辟新空间,次数过多,将会导致内存溢出。
示例一:

package com.dawndaybreak.ioexample;

import java.io.File;

/**
 * 递归输出所有文件到控制台
 * 
 * @author dawn
 * 
 */
public class RecursionDemoFirst {

	public static void main(String[] args) {
		File dir = new File("E:\\project");
		allFileList(dir, 0);
	}

	/**
	 * 将文件目录区分层次的显示到控制台
	 * 
	 * @param dir
	 *            文件目录
	 * @param level
	 *            分层级别
	 */
	private static void allFileList(File dir, int level) {
		File[] files = dir.listFiles();
		level++;
		for (File f : files) {
			if (f.isDirectory()) {
				// 如果是目录,调用本函数递归
				allFileList(f, level);
			} else {
				// 输出路径到控制台
				System.out.println(getLevel(level) + f);
			}
		}
	}

	private static String getLevel(int level) {
		StringBuilder sb = new StringBuilder();
		for (int i = level; i > 0; i--) {
			sb.append(" ");
		}
		sb.append("|-");
		return sb.toString();
	}

}

示例二:

package com.dawndaybreak.ioexample;

import java.io.File;

/**
 * 删除一个目录,因为file.delete()只能删除空目录,所以需要递归从内向外进行删除调用delete()先把所有文件删除,再删除文件夹
 * 
 * @author dawn
 * 
 */
public class RemoveDir {

	public static void main(String[] args) {
		File dir = new File("E:\\project\\delete");
		allDeleteFile(dir);
	}

	/**
	 * 删除指定目录
	 * 
	 * @param dir
	 */
	private static void allDeleteFile(File dir) {
		File[] files = dir.listFiles();
		for (File f : files) {
			if (f.isDirectory()) {
				// 如果是目录,继续调用本函数
				allDeleteFile(f);
			} else {
				// 如果是文件,直接删除
				f.delete();
			}
		}
		dir.delete();
	}

}


第二讲 Properties类

一、概述

1、Properties是Hashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术想结合的集合容器。
2、可用于键值对形式的配置文件。
3、在加载时,需要数据有固定的格式,常用的是:键=值。

二、特有方法

1、设置:调用调用 Hashtable 的方法 put,设置键和值。
      public Object setProperty(String key, String value)
2、获取: 用指定的键在此属性列表中搜索属性,如果找不到指定的key,返回null。
      public String getProperty(String key)
      返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
      public Set<String> stringPropertyNames()
3、加载流和存入流
      从输入流中读取属性列表(键和元素对)。
      public void load(InputStream inStream)
      按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
      public void load(Reader reader)
      将属性列表输出到指定的输出流。
      public void list(PrintWriter out)
      以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
      public void store(OutputStream out, String comments)
      以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
      public void store(Writer writer, String comments)
示例:

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(
				"E:/systemProperties.txt"));
		Properties prop = new Properties();
		String sLine = null;
		while ((sLine = br.readLine()) != null) {
			String[] arr = sLine.split("=");
			if (arr != null && arr.length == 2) {
				prop.put(arr[0], arr[1]);
			}
		}
		br.close();
		System.out.println(prop);
	}


第三讲 打印流

一、概述
      1、打印流包括:PrintStream和PrintWriter
      2、该流提供了打印方法,可将各种类型的数据都原样打印。
二、字节打印流:PrintStream
      构造方法中可接收的参数类型:
          1、File对象。File
          2、字符串路径:String
          3、字符输出流:OutputStream
三、字符串打印流:PrintWriter
      构造方法中可接受的参数类型
          1、File对象:File
          2、字符串路径:String
          3、字节输出流:OutputStream
          4、字符输出流:Writer

示例:

	public static void main(String[] args) throws IOException {
		// 获取键盘录入
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		// 打印流关联文件,自动刷新
		PrintWriter out = new PrintWriter("E:/log.log");
		String sLine = null;
		while ((sLine = br.readLine()) != null) {
			if ("0".equals(sLine)) {
				break;
			}
			out.println(sLine);
		}
		br.close();
		out.close();
	}


第四讲 序列流

一、概述
      1、SequenceInputStream对多个流进行合并。也被称为合并流。
      2、常用构造函数
          SequenceInputStream(Enumeration<?extends FileInputStream> e)
二、常见合并多个流文件步骤
      1、创建集合,并将流对象添加进集合
      2、创建Enumeration对象,将集合元素加入。
      3、创建SequenceInputStream对象,合并流对象
      4、创建写入流对象,FileOutputStream关联写入文件
      5、利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。

示例:

package com.dawndaybreak.ioexample;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.ListIterator;

/**
 * 合并流、切割文件
 * 
 * @author dawn
 * 
 */
public class StreamDemo {

	static int len;

	public static void main(String[] args) throws IOException {
		// 指定要切割的文件
		File sourceFile = new File("E:\\KuGou\\张杰 - 浩瀚.mp3");
		// 切割文件,且获取文件个数
		len = splitFile(sourceFile);

		// 指定合并多个文件到指定目标文件
		File targetFile = new File("E:/test/浩瀚.mp3");
		merge(targetFile);
	}

	/**
	 * 合并多个文件,输出到目标文件
	 * 
	 * @param targetFile
	 *            目标文件
	 * @throws IOException
	 */
	private static void merge(File targetFile) throws IOException {
		List<FileInputStream> listInputStream = new ArrayList<FileInputStream>();
		for (int i = 1; i <= len; i++) {
			listInputStream.add(new FileInputStream("E:/test/" + i + ".part"));
		}

		// 因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类
		final ListIterator<FileInputStream> lt = listInputStream.listIterator();
		Enumeration<FileInputStream> em = new Enumeration<FileInputStream>() {

			@Override
			public boolean hasMoreElements() {
				return lt.hasNext();
			}

			@Override
			public FileInputStream nextElement() {
				return lt.next();
			}
		};
		SequenceInputStream sis = new SequenceInputStream(em);

		FileOutputStream fos = new FileOutputStream(targetFile);
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = sis.read(buffer)) != -1) {
			fos.write(buffer, 0, len);
		}
		fos.close();
		sis.close();
	}

	/**
	 * 切割文件,返回文件切割个数
	 * 
	 * @param file
	 *            需要被切割的文件
	 * @throws IOException
	 *             return 文件个数
	 */
	private static int splitFile(File file) throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				file));
		BufferedOutputStream bos = null;

		byte[] buffer = new byte[1024 * 1024];
		int len = -1, x = 0;
		while ((len = bis.read(buffer)) != -1) {
			bos = new BufferedOutputStream(new FileOutputStream("E:/test/"
					+ ++x + ".part"));
			bos.write(buffer, 0, len);
			bos.close();
		}
		bis.close();
		return x;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值