黑马程序员-IO流(File类、Properties 类)

-----------android培训java培训、java学习型技术博客、期待与您交流! ------------


一、File类


1、概念:

文件和目录路径的抽象表现形式。

File这个名字有一定的误导性,它不单指文件。它既能代表一个特定文件的名称,又能代表一个目录下的一组文件的名称。


2、用途:

用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。这些是流对象办不到的,因为流只操作数据。

File对象可以作为参数传递给流的构造函数。


3、创建File对象方法:


方式1:File f1= new File("a.txt");//将a.txt封装成对象,可将已有和未出现的文件或文件夹封装成对象

方式2:File f2 = new File("c:\\abc","b.txt");//分别指定文件夹和文件。好处:降低了两者的关联程度

方式3:File d = new File("c:\\abc");     File f3 = new File(d,"c.txt");//可以传入父目录和文件名

方式4:目录分隔符。调用File.separator,方法如下:
File f4 = new File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"a.txt"); 


代码示例:

import java.io.*;

class FileDemo {
	// 创建File对象
	public static void consMethod() {
		// 将a.txt封装成file对象。可以将已有的和未出现的文件或者文件夹封装成对象。
		File f1 = new File("a.txt");

		File f2 = new File("c:\\abc", "b.txt");

		File d = new File("c:\\abc");
		File f3 = new File(d, "c.txt");

		sop("f1:" + f1);
		sop("f2:" + f2);
		sop("f3:" + f3);

		File f4 = new File("c:" + File.separator + "abc" + File.separator
				+ "zzz" + File.separator + "a.txt");
		sop("f4:" + f4);

	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}

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

}

/*output:
f1:a.txt
f2:c:\abc\b.txt
f3:c:\abc\c.txt
f4:c:\abc\zzz\a.txt
*/


4、File类常见方法:


(1)创建

boolean createNewFile():在指定目录下创建文件,如果该文件已存在,则不创建。而对操作文件的输出流而言,输出流对象已建立,就会创建文件,如果文件已存在,会覆盖。除非续写。
boolean mkdir():创建此抽象路径名指定的目录。
boolean mkdirs():创建多级目录。 


(2)删除

boolean delete():删除此抽象路径名表示的文件或目录。
void deleteOnExit():在虚拟机退出时删除。
注意:在删除文件夹时,必须保证这个文件夹中没有任何内容,才可以将该文件夹用delete删除。
window的删除动作,是从里往外删。注意:java删除文件不走回收站。要慎用。


代码示例:

import java.io.*;

class FileDemo1 {
	public static void method_1() throws IOException {
		File f = new File("file.txt");
		sop("create:" + f.createNewFile());
//		sop("delete:"+f.delete());
	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}

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

/*output:
create:true
*/


(3)判断

boolean exists():判断文件或者文件夹是否存在。
boolean isDirectory():测试此抽象路径名表示的文件是否是一个目录。
boolean isFile():测试此抽象路径名表示的文件是否是一个标准文件。
boolean isHidden():测试此抽象路径名指定的文件是否是一个隐藏文件。
boolean isAbsolute():测试此抽象路径名是否为绝对路径名。

 

代码示例:

import java.io.*;

class FileDemo2 {
	public static void method_2() {
		File f = new File("file.txt");

		sop("exists:" + f.exists());

		sop("execute:" + f.canExecute());

		// 创建文件夹
		File dir = new File("abc\\kkk\\a\\a\\dd\\ee\\qq\\aaa");

		sop("mkdir:" + dir.mkdirs());
	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}

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

/*output:
exists:true
execute:true
mkdir:true
*/

import java.io.*;

class FileDemo3 {

	public static void method_3() throws IOException {
		File f = new File("F:\\TIJ4-code\\io\\FileOutputShortcut.java");

		f.createNewFile();

		f.mkdir();

		// 记住在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在。
		// 通过exists判断。
		sop("dir:" + f.isDirectory());
		sop("file:" + f.isFile());

		sop(f.isAbsolute());
	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}

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

/*output:
dir:false
file:true
true
*/



(4)获取

long length():获取文件大小。
String getName():返回由此抽象路径名表示的文件或目录的名称。
String getPath():将此抽象路径名转换为一个路径名字符串。
String getAbsolutePath():返回此抽象路径名的绝对路径名字符串。
String getParent():返回此抽象路径名父目录的抽象路径名,如果此路径名没有指定父目录,则返回 null。
long lastModified():返回此抽象路径名表示的文件最后一次被修改的时间。
File.pathSeparator:返回当前系统默认的路径分隔符,windows默认为 “;”。
File.Separator:返回当前系统默认的目录分隔符,windows默认为 “\”。


代码示例:

import java.io.*;

class FileDemo4 {

	public static void method_4() {
		File f = new File("file.txt");

		sop("path:" + f.getPath());
		sop("abspath:" + f.getAbsolutePath());
		sop("parent:" + f.getParent());// 该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
										// 如果相对路径中有上一层目录那么该目录就是返回结果。
	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}

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

/*output:
path:file.txt
abspath:F:\Workspaces\workspace3\ioexer\file.txt
parent:null
*/

(5)获取全部:(非常重要!!!)

static File[] listRoots() 
          列出可用的文件系统根。(用于获取盘符)

String[] list() 
           返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 (返回指定目录下所有的文件或者文件夹的名称,包含隐藏文件)

           如果调用list方法的File 对象中封装的是一个文件,那么list方法返回数组为null。如果封装的对象不存在也会返回null。

           只有封装的对象存在并且是文件夹时,这个方法才有效。
String[] list(FilenameFilter filter) 
           返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。(只返回文件名字符串,属性单一) 
            注意:FilenameFilter接口只有一个方法:
                              boolean accept(File dir, String name) 测试指定文件是否应该包含在某一文件列表中,所以一般使用匿名内部类即可

File[] listFiles() 
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。(返回的是对象,包含多种属性,便于操作,开发时比较常用)

File[] listFiles(FileFilter filter) 
            返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
            注意:FileFilter接口只有一个方法:
                         boolean accept(File dir, String name) 测试指定文件是否应该包含在某一文件列表中,所以一般使用匿名内部类即可

5、递归:


(1)定义:

就是函数自身调用自身。


(2)什么时候用递归呢?

当一个功能被重复使用,而每一次使用该功能时的参数不确定,都由上次的功能元素结果来确定。
简单说:功能内部又用到该功能,但是传递的参数值不确定。(每次功能参与运算的未知内容不确定)。


(3)递归的注意事项:

1:一定要定义递归的条件。
2:递归的次数不要过多。容易出现 StackOverflowError 栈内存溢出错误。
其实递归就是在栈内存中不断的加载同一个函数。


代码示例1:

列出指定目录下文件或文件夹,包含子目录,即列出指定目录下所以内容

/*因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。
在列出过程中出现的还是目录的话,还可以再次调用本功能。
也就是函数自身调用自身。
这种表现形式,或者编程手法,称为递归。
 */

import java.io.*;

public class FileTest1 {
	public static void main(String[] args) {
		File dir = new File("F:\\myjava");
		System.out.println(dir.delete());
		showDir(dir, 0);

	}

	public static String getLevel(int level) {
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		for (int x = 0; x < level; x++) {
			sb.insert(0, "|  ");
		}
		return sb.toString();

	}

	public static void showDir(File dir, int level) {
		System.out.println(getLevel(level) + dir.getName());
		level++;
		File[] files = dir.listFiles();
		for (int x = 0; x < files.length; x++) {
			if (files[x].isDirectory())
				showDir(files[x], level);
			else
				System.out.println(getLevel(level) + files[x]);
		}

	}
}


代码示例2:删除一个带内容的目录。

删除原理:
在window中,删除目录从里面往外删除的。
既然是从里往外删除。就需要用到递归。

import java.io.*;

class RemoveDir {
	public static void main(String[] args) {

		File dir = new File("g:\\testdir");
		removeDir(dir);
	}

	public static void removeDir(File dir) {
		File[] files = dir.listFiles();

		for (int x = 0; x < files.length; x++) {
			if (files[x].isDirectory())
				removeDir(files[x]);
			else
				System.out.println(files[x].toString() + ":-file-:"
						+ files[x].delete());
		}

		System.out.println(dir + "::dir::" + dir.delete());
	}

}


代码示例3:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。

建立一个java文件列表文件。

思路:
1,对指定的目录进行递归。
2,获取递归过程所以的java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。

import java.io.*;
import java.util.*;

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

		File dir = new File("F:\\myjava");

		List<File> list = new ArrayList<File>();

		fileToList(dir, list);

		System.out.println(list.size());

		File file = new File(dir, "javalist.txt");
		writeToFile(list, file.toString());

	}

	public static void fileToList(File dir, List<File> list) {
		File[] files = dir.listFiles();

		for (File file : files) {
			if (file.isDirectory())
				fileToList(file, list);
			else {
				if (file.getName().endsWith(".java"))
					list.add(file);
			}
		}
	}

	public static void writeToFile(List<File> list, String javaListFile)
			throws IOException {
		BufferedWriter bufw = null;
		try {
			bufw = new BufferedWriter(new FileWriter(javaListFile));

			for (File f : list) {
				String path = f.getAbsolutePath();
				bufw.write(path);
				bufw.newLine();
				bufw.flush();
			}

		} catch (IOException e) {
			throw e;
		} finally {
			try {
				if (bufw != null)
					bufw.close();
			} catch (IOException e) {
				throw e;
			}
		}
	}
}

代码示例4:Java中实现复制文件或文件夹

 

分析: 拷贝一个文件的算法比较简单,当然,可以对它进行优化,比如使用缓冲流,提高读写数据的效率等。但是在复制文件夹时,则需要利用Flie类在目标文件夹中创建相应的目录,并且使用递归方法。

import java.io.*;

/**
 * 复制文件夹或文件夹
 */
public class CopyDirectory {
	// 源文件夹
	static String url1 = "f:/myjava";
	// 目标文件夹
	static String url2 = "h:/tempmyjava";

	public static void main(String args[]) throws IOException {
		// 创建目标文件夹
		(new File(url2)).mkdirs();
		// 获取源文件夹当前下的文件或目录
		File[] file = (new File(url1)).listFiles();
		for (int i = 0; i < file.length; i++) {
			if (file[i].isFile()) {
				// 复制文件
				copyFile(file[i], new File(url2 , file[i].getName()));
			}
			if (file[i].isDirectory()) {
				// 复制目录
				String sourceDir = url1 + File.separator + file[i].getName();
				String targetDir = url2 + File.separator + file[i].getName();
				copyDirectiory(sourceDir, targetDir);
			}
		}
	}

	// 复制文件
	public static void copyFile(File sourceFile, File targetFile)
			throws IOException {
		// 新建文件输入流并对它进行缓冲
		FileInputStream input = new FileInputStream(sourceFile);
		BufferedInputStream inBuff = new BufferedInputStream(input);

		// 新建文件输出流并对它进行缓冲
		FileOutputStream output = new FileOutputStream(targetFile);
		BufferedOutputStream outBuff = new BufferedOutputStream(output);

		// 缓冲数组
		byte[] b = new byte[1024 * 5];
		int len;
		while ((len = inBuff.read(b)) != -1) {
			outBuff.write(b, 0, len);
		}
		// 刷新此缓冲的输出流
		outBuff.flush();

		// 关闭流
		inBuff.close();
		outBuff.close();
		output.close();
		input.close();
	}

	// 复制文件夹
	public static void copyDirectiory(String sourceDir, String targetDir)
			throws IOException {
		// 新建目标目录
		(new File(targetDir)).mkdirs();
		// 获取源文件夹当前下的文件或目录
		File[] file = (new File(sourceDir)).listFiles();
		for (int i = 0; i < file.length; i++) {
			if (file[i].isFile()) {
				// 源文件
				File sourceFile = file[i];
				// 目标文件
				File targetFile = new File(
						new File(targetDir).getAbsolutePath() + File.separator
								+ file[i].getName());
				copyFile(sourceFile, targetFile);
			}
			if (file[i].isDirectory()) {
				// 准备复制的源文件夹
				String dir1 = sourceDir + "/" + file[i].getName();
				// 准备复制的目标文件夹
				String dir2 = targetDir + "/" + file[i].getName();
				copyDirectiory(dir1, dir2);
			}
		}
	}
}


 


二、Properties 类


1、概述:

Properties是Hashtable的子类,它具备Map集合的特点,里面存储的是键值对,都是字符串,无泛型定义。是集合中和IO技术相结合的集合容器。


2、特点:

(1)可用于键值对形式的配置文件
(2)在加载时,需要数据有固定的格式,常用的是:键=值


3、特有方法:

Object setProperty(String key, String value) 调用 Hashtable 的方法 put。(改变的是内存中的结果)
String getProperty(String key) 用指定的键在此属性列表中搜索属性。 
Set<String> stringPropertyNames() 
返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键 

代码示例:

import java.io.*;
import java.util.*;

class PropertiesDemo {
	public static void main(String[] args) throws IOException {
		setAndGet();
	}

	// 设置和获取元素。
	public static void setAndGet() {
		Properties prop = new Properties();

		prop.setProperty("zhangsan", "30");
		prop.setProperty("lisi", "39");

		System.out.println(prop);
		String value = prop.getProperty("lisi");
		System.out.println(value);

		prop.setProperty("lisi", 89 + "");

		Set<String> names = prop.stringPropertyNames();
		for (String s : names) {
			System.out.println(s + ":" + prop.getProperty(s));
		}
	}
}

/*output:
{zhangsan=30, lisi=39}
39
zhangsan:30
lisi:89
*/

void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。 
void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 

void store(OutputStream out, String comments) 

以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 
        (将内存的结果存到一个流中,并存到文件上)

void store(Writer writer, String comments) 
以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 

void list(PrintStream out) 将属性列表输出到指定的输出流。 
void list(PrintWriter out) 将属性列表输出到指定的输出流。
代码示例:

import java.io.*;
import java.util.*;

class PropertiesDemo3 {
	public static void main(String[] args) throws IOException {
		loadDemo();
	}

	public static void loadDemo() throws IOException {
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream("info.txt");

		// 将流中的数据加载进集合。
		prop.load(fis);

		prop.setProperty("wangwu", "39");

		FileOutputStream fos = new FileOutputStream("info.txt");

		prop.store(fos, "haha");

		System.out.println(prop);
		prop.list(System.out);

		fos.close();
		fis.close();

	}
}

/*output:
{wangwu=39}
-- listing properties --
wangwu=39
*/


练习1:演示load方法的原理:如何将流中的数据存储到集合中

想要将info.txt中键值数据存到集合中进行操作。

1,用一个流和info.txt文件关联。 

2,读取一行数据,将该行数据用"="进行切割。
3,等号左边作为键,右边作为值。存入到Properties集合中即可。

import java.io.*;
import java.util.*;

class PropertiesDemo2 {

	// 将流中的数据存储到集合中
	public static void loadMethod() throws IOException {
		BufferedReader bufr = null;
		try {
			Properties pop = new Properties();
			bufr = new BufferedReader(new FileReader("info.txt"));
			String line = null;
			while ((line = bufr.readLine()) != null) {
				String[] arr = line.split("=");
				pop.setProperty(arr[0], arr[1]);
			}
			System.out.println(pop);
		} catch (IOException e) {
			throw new RuntimeException("文件操作失败");
		} finally {
			try {
				if (bufr != null)
					bufr.close();
			} catch (IOException e) {
				throw new RuntimeException("关闭流资源操作失败");
			}
		}
	}

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


练习2:用于记录应用程序运行次数

用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。

很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。
下一次再启动该程序,又重新开始从0计数。这样不是我们想要的。

我们需要程序即使结束,该计数器的值也存在。下次程序启动在会先加载该计数器的值并加1后再重新存储起来。
所以要建立一个配置文件。用于记录该软件的使用次数。该配置文件使用键值对的形式。这样便于阅读数据,并操作数据。
键值对数据是map集合。数据是以文件形式存储,使用io技术。那么map+io -->properties.

配置文件可以实现应用程序数据的共享。

import java.util.*;
import java.io.*;

class RunCount {
	public static void main(String[] args) throws IOException {
		// 创建一个Properties对象,集合和io的结合
		Properties pop = new Properties();
		// 创建一个文件对象,用于操作文件
		File file = new File("count.ini");
		// 先判断文件是否存在,如果不存在就创建一个
		if (!file.exists())
			file.createNewFile();

		// 创建读取流对象,读取文件中的信息
		FileInputStream fis = new FileInputStream(file);
		// 将流中的文件信息存入集合中
		pop.load(fis);

		// 定义计数器
		int count = 0;
		// 获取文件中键所对应的值
		String value = pop.getProperty("time");
		// 判断值是否为null,不为空就将值传给计数器
		if (value != null) {
			count = Integer.parseInt(value);
			// 判断计数器是否为到达次数
			if (count >= 5) {
				System.out.println("次数已到,请注册");
				return;
			}
		}
		count++;
		// 将获得的键值设置后存入集合中
		pop.setProperty("time", count + "");
		FileOutputStream fos = new FileOutputStream(file);
		pop.store(fos, "");
		fos.close();
		fis.close();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值