[置顶] JavaSE 拾遗(11)——JavaSE IO...(2)


使用 java.io 包中的类,先确定数据传输的方向和数据交换的设备,之后再根据需要的功能添加其他数据处理类,比如 BufferedXXX、Properties、InputStreamReader、outputStreamWriter 之类,添加其他数据处理的类的时候,根据数据处理的逻辑顺序,顺序添加。

File

File类是IO包中代表文件系统中文件和文件夹的类,File类定义了一些与平台无关的方法来操作文件和文件夹,可以通过调用File类中的方法,实现 创建、删除、重命名文件等,File类是对象还可以用来获取未文件本身的一些属性信息,如文件所在的目录、文件的长度、文件的读写权限等。IO流可以将数据写入到文件中, 而文件也是IO流提供数据源或者数据目的地的对象。
 

构造方法:

 File(File parent, String child) parent:子路径字符串  child:父路径字符串

根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。

 File(String pathname) pathname指包括文件路径(包文件名)

通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

 File(String parent, String child) 
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
 File(URI uri) 
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。


File类常见方法:

1、创建

boolean createNewFile() 在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样的是输出流对象默认会覆盖。
boolean mkdir() 创建文件夹。

boolean mkdirs()创建多级文件夹。

示例:
    File f=new File("file.txt");     
    sop("create:"+f.createNewFile()); //创建文件  
    sop("mkdir:"+f.mkdir()); //创建文件夹   
    sop("mkdir:"+f.mkdirs()); //创建多级的文件夹 

2、删除

    boolean delete()删除失败返回false。如果文件正在被使用,则删除不了返回 false。
    void deleteOnExit()在程序退出时删除指定文件。

示例:
    File f=new File("file.txt");
    f.deleteOnExit(); //程序退出时删除指定文件
    sop("create:"+f.createNewFile()); //创建文件
    sop("delete:"+f.delete()); //删除文件

3、判断
    boolean  exists()文件是否存在.
    boolean  isFile()判断是否是文件
    boolean isDirectory()是否是一个目录
    boolean isHidden()判断是是否是隐藏的文件
    boolean isAbsolute()测试此抽象路径名是否为绝对路径名

示例:
    File f = new File("d:\\java1223\\day20\\file2.txt");
    sop("dir:"+f.isDirectory());
    sop("file:"+f.isFile());
    sop(f.isAbsolute());

在判断文件对象是否是文件或者目的之前,必须要先通过exists判断该文件对象中路径所指的文件或者文件夹在文件系统中是否存在。

4、获取信息

String getName()返回由此抽象路径名表示的文件或目录的名称。

String getPath()将此抽象路径名转换为一个路径名字符串。
String getParent()返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。如果相对路径中有上一层目录那么该目录就是返回结果。
String getAbsolutePath()返回此抽象路径名的绝对路径名字符串。
long lastModified()返回此抽象路径名表示的文件最后一次被修改的时间。
long length()返回由此抽象路径名表示的文件的长度.

示例:

File f = new File("file.txt");

sop("path:"+f.getPath());

sop("abspath:"+f.getAbsolutePath()); 该方法返回程序运行时的 file 对象的绝对路径
sop("parent:"+f.getParent()); 该方法返回的是指定路径中的父目录。如果获取的是相对路径,相对路径中有上一层目录那么该目录就是返回结果。

5、其他:
static File[] listRoots()列出可用的文件系统根。
File[] listFiles()返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
String[] list()返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录

		File f = new File("d:\\");
		String[] nums = f.list();// 列出文件和目录。
		for (String s : nums)// 高级for
		{
			System.out.println(s);
		}

	public static void listRoots() {
		File[] files = File.listRoots(); // 列出可用的文件系统根。
		for (File f : files) // 高级for
		{
			System.out.println(f);
		}
	}

函数递归

函数递归又叫函数嵌套,是指在函数定义的时候调用函数自己

注意:递归时一定要明确结束条件。 

应用场景:当某一功能要重复使用时,可以使用函数递归,函数递归的好处是简化了算法的描述方法,但是是因为函数压栈弹栈,和循环相比降低了程序的运行效率

递归要注意:
  1、限定条件。
  2、要注意递归的次数。尽量避免内存溢出。

函数递归使用实例:列出指定目录下文件或者文件夹,包含子目录中的内容。

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


示例:

package cn.itcast.others.iostream;

import java.io.File;

class Test {
	public static void main(String[] args) {
		File f = new File("d:\\j2se 练习");
		showDir(f);
	}

	public static void showDir(File dir) {
		File[] files = dir.listFiles(); // 调用 listFiles() 方法,获取当前目录下的每个文件或目录

		for (File f : files) {
			if (f.isDirectory()) // 对元素进行判断是否是文件夹.如果是使用递归.
				showDir(f);
			System.out.println(f);
		}
	}
}

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

package cn.itcast.others.iostream;

import java.io.File;

class RemoveDir {
	public static void main(String[] args) {
		File dir = new File("d:\\testdir");
		removeDir(dir);
	}

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

		for (int x = 0; x < files.length; x++) // 遍历File数组
		{
			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()); // 删除完文件,就把文件夹删掉
	}
}

练习: 将一个指定目录下的 java 文件的绝对路径存储到一个文本文件中, 建立一个java文件列表文件

/**
 * 思路
 * 1.对指定的进行递归.
 * 2.获取递归过程总所有的java文件的路径.
 * 3.将这些路径存储到集中.
 * 4.将集合整蛊你的数据写入到一个文件中
 */
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

class JavaFileList {
	public static void main(String[] args) {
		File dir = new File("d:\\java0410");// 建立File对象.指定路径
		List<File> list = new ArrayList<File>();// 建立list集合存储递归到的文件
		fileToList(dir, list);// 往fileToList函数里面传入路径和集合

		try {
			// 创建路径javalist.txt文本文件
			File file = new File(dir, "javalist.txt");
			writeToFile(list, file.toString());// 传入到writeToFile函数中
		} catch (IOException e) {
			throw new RuntimeException("创建失败");
		}

	}

	public static void fileToList(File dir, List<File> list) {
		File[] files = dir.listFiles();// 获取路径的文件和文件夹

		for (File file : files)// 高级for循环.File文件类型 file变量名字 files被变量的数组(或集合)
		{
			if (file.isDirectory())// 判断是否是文件夹.如果是文件件.就递归,进文件夹里面.
				fileToList(file, list);// 递归穿进去刚才判断的文件夹.list集合也穿进去.因为文件都存在一个集合中
			else {
				if (file.getName().endsWith(".java"))// 如果是文件的话.就判断是否后缀名是.java的文件
					list.add(file);// 往集合中存入文件
			}
		}
	}

	// 将集合中的数据存入到文本文件中
	public static void writeToFile(List<File> list, String javaListFile)
			throws IOException {
		BufferedWriter bufw = null;// 初始化BufferedWrite容器.
		try {
			// 建立BufferedWriter字符输出流.并指定文件路径javaListFile就是路径
			bufw = new BufferedWriter(new FileWriter(javaListFile));
			for (File f : list)
			{
				String path = f.getAbsolutePath();// 返回此抽象路径名的绝对路径名字符串。
				bufw.write(path);// 将字符传输出到文本文件javalist.txt中
				bufw.newLine();// 换行
				bufw.flush();// 刷新
			}
		} catch (IOException e) {
			throw e;// 抛出异常
		} finally {
			try {
				if (bufw != null)// 判断是否建立失败
					bufw.close();
			} catch (IOException e) {
				System.out.println("关闭字符输出流失败");
				throw e;
			}
		}
	}
}
关于递归函数更详细分析看 这里

Properties

Properties是 HashTable 的子类,它具备 Map 集合的特点。而且它里面存储的都是字符串键值对。Properties 是集合和 IO 技术相结合的集合容器。

该对象的特点:可以用于键值对形式的配置文件,在加载数据时,需要数据有固定格式:键=值,#表示注释。


构造方法

 Properties() 创建一个无默认值的空属性列表。
 Properties(Properties defaults) 创建一个带有指定默认值的空属性列表。

常用方法

String getProperty(String key) 用键获取值.

Object setProperty(String key, String value) 设置键值对.调用 Hashtable 的方法 put。

Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。


实例:

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

class SequenceDemo {
	public static void main(String[] args) throws IOException {
		Vector<FileInputStream> v = new Vector<FileInputStream>();// 建立枚举

		v.add(new FileInputStream("d:\\1.txt"));
		v.add(new FileInputStream("d:\\2.txt"));// 添加对象
		v.add(new FileInputStream("d:\\3.txt"));

		Enumeration<FileInputStream> en = v.elements();// 使用枚举的elements,.返回Enumeration,SequenceInputStream就可以使用了

		SequenceInputStream sis = new SequenceInputStream(en);

		FileOutputStream fos = new FileOutputStream("d:\\4.txt");// 建立字符输出流.和文件相关联

		byte[] buf = new byte[1024];// 建立字符数组还缓冲

		int len = 0;
		while ((len = sis.read(buf)) != -1) {
			fos.write(buf, 0, len);
		}
		fos.close();// 关闭流
		sis.close();
	}
}

void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。

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

实例:

	public static void loadDemo() throws IOException {
		FileReader fr = new FileReader("info.txt");// 建立字符输入流对象与文件相关联

		Properties prop = new Properties();// 建立Properties属性类

		prop.load(fr);// 使用Properties的load方法.将字符输入流的数据转入Properties中

		System.out.println(prop);

		prop.setProperty("zhangsan", "88");// 将info.txt中到底值设置为88

		FileOutputStream fos = new FileOutputStream("info.txt");// 建立字节输出流和文件相关联

		prop.store(fos, "haha");// 使用Properties的store方法,将流流中的数据存储到指定的文件中

		System.out.println(prop);

		fr.close();// 关闭流

		fos.close();
	}

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

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

class RunCountDemo {
	public static void main(String[] args) {
		count();// 调用count方法
	}

	public static void count() {
		// 给对象初始化属性类
		Properties prop = null;
		File file = null;
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {

			prop = new Properties(); // 创建Properties属性类对象

			file = new File("count.ini");// 创建File文件对象

			if (!(file.exists()))// 对file进行判断是否存在.如果不存在创建一个.
				file.createNewFile();

			fis = new FileInputStream(file); // 建立字节输入流对象.和文件相关联

			prop.load(fis);// 将流转换成Properties

			int count = 0;// 计数器

			String value = prop.getProperty("timp"); // 获取timp的值.

			if (value != null)// 判断是否为空
			{
				count = Integer.parseInt(value); // 如果不等于空的话将值转换成Integet对象进行操作
				if (count >= 5)// 如果判断等于>=5程序跳出
				{
					System.out.println("使用次数已经到");
					return;
				}
			}
			count++;// 计数器加加

			fos = new FileOutputStream(file);// 创建字符输出流.和文件相关联

			prop.setProperty("timp", count + "");// 设置键值.

			prop.store(fos, "haha");// 将流流中的数据存储到指定的文件中

		} catch (IOException e)// 异常处理
		{
			throw new RuntimeException("配置文件创建失败" + e.toString());
		} finally {
			try {
				if (fis != null)
					fis.close();
			} catch (IOException e) {
				throw new RuntimeException("关闭输入流失败");
			}
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
				throw new RuntimeException("关闭输出流失败");
			}

		}
	}
}

打印流

该流提供了打印方法,可以将各种数据类型的数据都原样打印。

字节打印流 PrintStream

构造函数可以接收的参数类型: 
1、file对象 File
2、字符串路径   String
3、字节输出流 OutputStream
4、PrintStream(OutputStream out, boolean autoFlush)
autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区

字符打印流 PrintWriter

向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。
构造函数可以接收的参数类型:
1、file对象。File
2、字符串路径。String
3、字节输出流。OutputStream
4、字符输出流,Writer。
5、PrintWriter(OutputStream out, boolean autoFlush)
autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区,与 PrintStream 类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。
实例:

import java.io.*;

class PrintWriterDemo {
	public static void main(String[] args) throws IOException {
		BufferedReader bufr = // 键盘录入
		new BufferedReader(new InputStreamReader(System.in));

		PrintWriter out = new PrintWriter(System.out, true);// 打印流对象

		String len = null;

		while ((len = bufr.readLine()) != null) {
			if ("over".equals(len))
				break;
			out.println(len.toUpperCase());// 打印.并转成大写
		}
	}
}

合并流 SequenceInputStream   (合并输入流)

构造方法

SequenceInputStream(Enumeration<? extends InputStream> e)Enumeration:枚举

SequenceInputStream(InputStream s1, InputStream s2)通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。 

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

class SequenceDemo {
	public static void main(String[] args) throws IOException {
		Vector<FileInputStream> v = new Vector<FileInputStream>();// 建立枚举

		v.add(new FileInputStream("d:\\1.txt"));
		v.add(new FileInputStream("d:\\2.txt"));// 添加对象
		v.add(new FileInputStream("d:\\3.txt"));

		Enumeration<FileInputStream> en = v.elements();// 使用枚举的elements,.返回Enumeration,SequenceInputStream就可以使用了

		SequenceInputStream sis = new SequenceInputStream(en);

		FileOutputStream fos = new FileOutputStream("d:\\4.txt");// 建立字符输出流.和文件相关联

		byte[] buf = new byte[1024];// 建立字符数组还缓冲

		int len = 0;
		while ((len = sis.read(buf)) != -1) {
			fos.write(buf, 0, len);
		}
		fos.close();// 关闭流
		sis.close();
	}
}

/*
需求:切割一个MP4文件.,并合并

 步骤..
  切割:
  1.建立字符输入流和文件相关联
  2.建立输出流.输出的时候分三个文件存储.

 合并:
  1.使用枚举的elements.返回Enumeration,因为合并流需要
  2.往枚举里添加字节输入流对象.
  3.建立输出流.和文件路径文件名关联.
  4.输出.
  
 */
import java.io.*;

import java.util.*;

class SplitFile {
	public static void main(String[] args) {
		// split()
		merge();
	}

	public static void merge()// 合并文件
	{
		FileOutputStream fos = null;// 初始化字节输入流对象
		SequenceInputStream sis = null;// 初始化字节输入流对象合并流
		try {
			Vector<FileInputStream> v = new Vector<FileInputStream>();// 建立枚举
			for (int x = 0; x < 3; x++) {
				v.add(new FileInputStream("d:\\" + x + ".mp4"));// for循环添加遍历对象.
			}

			Enumeration<FileInputStream> en = v.elements();// //使用枚举的elements,.返回Enumeration,SequenceInputStream就可以使用了

			sis = new SequenceInputStream(en);// 建立合并流,往合并流中传入

			fos = new FileOutputStream("d:\\4.mp4");// 建立字符输出流对象.并指定文件

			byte[] buf = new byte[1024 * 1024 * 10];// 建立字符数组10M的

			int len = 0;
			while ((len = sis.read(buf)) != -1) {
				fos.write(buf, 0, len);// 往容器中存数据.
			}
		} catch (IOException e)// 异常
		{
			throw new RuntimeException("文件合并失败");
		} finally {
			try {
				if (fos != null)
					fos.close();
			} catch (IOException e) {
				System.out.println("关闭流资源失败");
			}
			try {
				if (sis != null)
					sis.close();
			} catch (IOException e) {
				System.out.println("关闭流资源失败");
			}
		}
		// fos.close();
		// sis.close();

	}

	public static void split()// 切割
	{
		FileInputStream fis = null;// 初始化对象
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream("d:\\VID_20130414_181841.mp4");// 字符输入流指定文件
			byte[] buf = new byte[1024 * 1024 * 10];

			int len = 0;
			int count = 0;// 定义变量来当名字

			while ((len = fis.read(buf)) != -1) {
				fos = new FileOutputStream("d:\\" + (count++) + ".mp4");// 指定路径和文件名字
				fos.write(buf, 0, len);// 开始输出.
				fos.close();
			}
		} catch (IOException e) {
			throw new RuntimeException("文件切割失败");
		} finally {
			try {
				if (fis != null)
					fis.close();
			} catch (IOException e) {
				System.out.println("关闭流资源失败");
			}
		}

	}
}

你可能感兴趣的:(JavaSE,IO流)