Java基础视频教程第20天_IO流之File、递归

一、IO流 —— File 概述

	1、 File 是文件和目录路径名的抽象表示形式。
		作用:
			用来将文件或者文件夹封装成对象;
			方便对文件与文件夹的属性信息进行操作;
			File 对象可以作为参数传递给流的构造函数。

	java.lang.Object 
		-java.io.File
		public class File extends Object implements Serializable, Comparable<File> 

	2、字段摘要:
		static String separator
			与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
			
	3、示例代码:
	import java.io.*;
	class FileDemo
	{
		public static void main(String[] args)
		{
			//目录分隔符
			String se = File.separator;

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

			File f2 = new File("d:"+se+"abc","b.txt");

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

			//打印:封装的是什么,就打印什么
			System.out.println("f1="+f1);// a.txt
			System.out.println("f2="+f2);// d:\abc\b.txt
			System.out.println("f3="+f3);// d:\abc\c.txt 
		}
	}

二、 File 对象功能——创建和删除

File 类的常见方法:

1、创建
boolean createNewFile(); 在指定位置创建文件;如果该文件已经存在,则不创建。该方法会抛出 IOException 。

static File createTempFile(String prefix, String suffix);在默认临时文件目录中创建一个空文件。

static File createTempFile(String prefix, String suffix, File directory); 在指定目录中创建一个新的空文件。

boolean mkdir(); 只能创建一级目录;如果目录已经存在,则不创建。

boolean mkdirs(); 可以创建多级目录,也可以创建一级目录;同上。

2、删除
boolean delete(); 删除文件。注意,如果一个文件正在被使用,或者在读取到delete这段代码之前,程序发生异常;那么有可能删除文件不成功。
对于一些临时文件就可以调用deleteOnExit()方法删除。

void deleteOnExit(); 在退出时删除。

示例代码:
	import java.io.*;
	class FileDemo2
	{
		public static void main(String[] args)
		{
			method_1();
			method_2();
		}
		public static void method_1() throws IOException
		{
			File f = new File("file.txt");
			//f.deleteOnExit();

			boolean bl = f.createNewFile();
			System.out.println(bl);

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

		public static void method_2()
		{
			File dirs = new File("a\\b\\c");
			File dir = new File("abc");

			System.out.println("dirs: "+dirs.mkdirs());
			System.out.println("dir: "+dir.mkdir());
		}
	}

三、 File 对象功能——判断

3、判断
boolean canExecute(); 可否执行

boolean exists(); 文件或文件夹是否存在

boolean isDirectory(); 是否是目录

boolean isFile(); 是否是文件 

boolean isHidden(); 是否是隐藏文件

boolean isAbsolute(); 是否是绝对路径名

代码:
	import java.io.*;
	class FileDemo3
	{
		public static void main(String[] args)
		{
			method_3();
			method_4();
		}
		public static void method_3()
		{
			File f = new File("file.txt");

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

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

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

			//f.createNewFile();
			sop("mkdir: "+f.mkdir());

			//在判断文件对象是否是文件或者目录时,必须先判断该文件对象封装的内容是否存在。
			//通过 exists() 判断。
			sop("exists: "+f.exists());
			sop("dir: "+f.isDirectory());
			sop("file: "+f.isFile());
		}
		public static void sop(Object obj)
		{
			System.out.println(obj);
		}
	}

四、 File 对象功能——获取

4、获取信息
String getName(); 获取文件或者目录名
String getParent(); 获取绝对路径中的父目录,如果此路径名没有指定父目录,则返回 null 。
String getPath(); 获取路径名(封装什么,就返回什么)
String getAbsolutePath(); 获取绝对路径 
File getAbsoluteFile(); 获取绝对路径对象
long lastModified(); 获取最后修改时间
long length(); 获取文件的长度,参考 int available() 

boolean renameTo(File dest); 重命名文件对象。实际上是创建新文件,并将原文件中的内容复制到新文件中,同时删除原有文件。

功能代码:
	public static void method_5()throws IOException
	{
		//File f = new File("d:\\abc\\a.txt");
		File f = new File("file.txt");
		f.createNewFile();

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

		sop("getNme: "+f.getName());
		sop("getParent: "+f.getParent());

		sop("lastModefied: "+f.lastModified());
		sop("length: "+f.length());
	}
	public static void method_6()
	{
		File f1 = new File("d:\\file.txt");
		File f2 = new File("rename.txt");

		sop("rename: "+f1.renameTo(f2));
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}

五、 File 对象功能——文件列表

static File[] listRoots(); 获取盘符

String[] list(); 列出指定目录中的文件和文件夹,包括隐藏部分。调用该方法的 File 对象必须是封装了一个目录,该目录还必须存在。

功能代码:
	public static void listRootsDemo()
	{
		File[] files = File.listRoots();
		/*
		for (int x=0 ;x<files.length ;x++ )
		{
			System.out.println(files[x]);
		}
		*/
		for(File f : files)
		{
			System.out.println(f);
		}
	}

	public static void listDemo()
	{
		File f = new File("d:\\");

		String[] names = f.list();
		for(String name : names)
		{
			System.out.println(name); 
		}
	}

六、 File 对象功能——文件列表

java.io.FilenameFilter 
public interface FilenameFilter 
该接口只有一个方法: boolean accept(File dir, String name); 测试指定文件是否应该包含在某一文件列表中。

String[] list(FilenameFilter filter); 返回满足指定过滤器的文件名和目录名

File[] listFiles(); 
File[] listFiles(FileFilter filter); 
File[] listFiles(FilenameFilter filter);
返回的是 File 对象。

功能代码:
	public static void listDemo_2()
	{
		File dir = new File("d:\\java\\javadiary\\day20");

		String[] arr = dir.list(new FilenameFilter()
		{
			public boolean accept(File dir, String name)
			{
				//System.out.println("dir: "+dir+"---name: "+name);
				//return true;
				return name.endsWith(".java");
			}
		});

		System.out.println("length: "+arr.length);

		for(String name : arr)
		{
			System.out.println(name); 
		}
	}

	public static void listDemo_3()
	{
		File dir = new File("d:\\java\\javadiary\\day20");

		File[] files = dir.listFiles();

		for(File f : files)
		{
			System.out.println(f.getName()+"::"+f.length());
		}
	}

七、列出目录下所有内容——递归 

程序调用自身的编程技巧称为递归(recursion)。(来自网络释义)

需求:列出指定目录下的文件或者文件夹,包含子目录中的内容。
也就是列出指定目录下的所有内容。

思路:因为目录中还有目录,只要使用同一个列出目录的功能调用函数即可;在列出过程中出现的还是目录的话,还可以再次调用本功能;也就是函数自身调用自身;这种编程手法称为递归。
代码见下一节。

递归要注意:
1、限定条件;
2、注意递归次数,避免内存溢出。
===当递归次数过多时,栈内存中调用的方法也过多,会出现内存溢出。

代码示例:
	class RecursionDemo
	{
		public static void main(String[] args)
		{
			int sum = getSum(5);
			System.out.println("sum="+sum);//15
			toBin(6);//110
		}
		public static int getSum(int n)
		{
			if(n==1)
				return 1;
			else
				return n+getSum(n-1);
		}
		public static void toBin(int num)
		{
			if(num>0)
			{
				toBin(num/2);
				System.out.print(num%2);
			}
		}
	}

八、列出目录下所有内容——带层次

上一节优化后代码:
	class FileDemo
	{
		public static void main(String[] args) 
		{
			File dir = new File("d:\\java\\javadiary");
			showDir(dir,0);
		}
		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]);
			}
		}
		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();
		}
	}

九、删除带内容的目录 

删除原理:
在window中,删除目录是从里面往外删除的。
用递归可以解决。

代码:
	import java.io.*;
	class RemoveDir 
	{
		public static void main(String[] args) 
		{
			File dir = new File("d:\\abc");
			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()+":--:"+files[x].delete());
			}
			System.out.println(dir+"::dir::"+dir.delete());
		}
	}

十、创建java文件列表 

练习:
将一个指定目录下的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("d:\\java\\javadiary");

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

十一、 Properties 简述 

java.util.Dictionary 
-Hashtable
-Properties 

Properties 是 Hashtable 的子类,也就是说它具备 Map 集合的特点,而且它里面存储的键值对都是字符串。

它是集合中和IO技术相结合的集合容器。
该对象的特点:
可以用于键值对形式的配置文件。 
在加载数据时,需要数据有固定格式:键=值

十二、 Properties 存取 

Properties 的基本常用方法:
String getProperty(String key) :用指定的键在此属性列表中搜索属性。 
Object setProperty(String key, String value) :调用 Hashtable 的方法 put。也就相当于添加。
Set<String> stringPropertyNames() :返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。 

	class PerpertiesDemo
	{
		public static void main(String[] args)
		{
			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="+value);

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

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

十三、 Properties 存取配置文件 

演示:如何将流中的数据存储到集合中。
将info.txt中键值对数据存到集合中。
思路:
1、用一个流和info.txt文件关联;
2、读取一行数据,将该行数据用"="切割;
3、等号左边作为键,右边作为值,存入到Properties集合中即可。

	public static void method_1() throws IOException 
	{
		BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));

		String line = null;

		Properties prop = new Properties();

		while((line=bufr.readLine())!=null)
		{
			String[] arr = line.split("=");
			//System.out.println(arr[0]+"...."+arr[1]);
			prop.setProperty(arr[0],arr[1]);
		}

		bufr.close();
		System.out.println(prop);
	}

以上方法为早期做法,JDK1.6版本后, Properties 有一个方法load()可以直接加载文件中的配置信息:
void load(InputStream inStream) :从输入流中读取属性列表(键和元素对)。 
void load(Reader reader) :按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。

其他常用方法:
void store(OutputStream out, String comments) :将 Properties 表中的属性列表(键和元素对)写入输出流。
void store(Writer writer, String comments) :将 Properties 表中的属性列表(键和元素对)写入输出字符。

代码示例如下:
	public static void loadDemo() throws IOException
	{
		//创建一个字节读取流
		FileInputStream fis = new FileInputStream("info.txt");

		Properties prop = new Properties();

		//将流中的数据加载进集合
		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();
	}

=====凡是每行开头带#的都代表注释信息,不会被 Properties 加载。

十四、 Properties 练习 

需求:
使用一个配置文件,用于记录应用程序运行次数:
如果使用次数已到,那么给出注册提示。

思路:
用 Propertied 存储计数器的数据。
	import java.io.*;
	import java.util.*;
	class  RunCount
	{
		public static void main(String[] args) throws IOException 
		{
			Properties prop = new Properties();

			//先将文件封装成对象
			File file = new File("count.ini");

			if(!file.exists())
				file.createNewFile();

			FileInputStream fis = new FileInputStream(file);

			prop.load(fis);

			int count = 0;
			String value = prop.getProperty("time");

			if(value!=null)
			{
				count = Integer.parseInt(value);
				if(count>=5)
				{
					System.out.println("使用次数已到");
					return ;
				}
			}

			count++;

			prop.setProperty("time", count+"");

			FileOutputStream fos = new FileOutputStream(file);

			prop.store(fos,"");

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

十五、 PrintWriter 

java.lang.Object 
-java.io.Writer 
java.io.PrintWriter 
public class PrintWriter extends Writer 

java.lang.Object 
-java.io.OutputStream 
-java.io.FilterOutputStream 
-java.io.PrintStream 
public class PrintStream extends FilterOutputStream implements Appendable, Closeable 

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

PrintStream: 字节打印流 
构造函数可以接收的参数类型:
1、file对象: File
2、字符串路径: String
3、字节输出流: OutputStream 

PrintWriter: 字符打印流 
构造函数可以接收的参数类型:
1、file对象: File
2、字符串路径: String
3、字节输出流: OutputStream 
4、字符输出流: Writer 

代码:
	import java.io.*;
	class PrintStreamDemo 
	{
		public static void main(String[] args) throws IOException  
		{
			BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

			//PrintWriter out = new PrintWriter(System.out, true);
			PrintWriter out = new PrintWriter(new FileWriter("a.txt"), true);//构造函数中传入true参数,该流可以自动刷新

			String line = null;

			while((line=bufr.readLine())!=null)
			{
				if("over".equals(line))
					break;
				out.println(line.toUpperCase());
				//out.write(line.toUpperCase());
				//out.write("\r\n");
				//out.flush();
			}

			out.close();
			bufr.close();
		}
	}

十六、合并流

java.lang.Object 
-java.io.InputStream 
-java.io.SequenceInputStream 

序列流: 
SequenceInputStream : 对多个流进行合并。该类是 InputStream 的子类,因此它是一个字节读取流。

构造方法:
SequenceInputStream(Enumeration<? extends InputStream> e);
			该构造方法接收一个 Enumeration 对象,该对象中定义的泛型是 InputStream 类型或者子类类型,可用于合并多个字节流。
		SequenceInputStream(InputStream s1, InputStream s2);
			该构造方法接收两个 InputStream ,用于合并两个字节流。

	代码:
	import java.util.*;
	import java.io.*;
	class SequenceDemo
	{
		public static void main(String[] args) throws IOException  
		{
			Vector<FileInputStream> v = new Vector<FileInputStream>();

			v.add(new FileInputStream("1.txt"));
			v.add(new FileInputStream("2.txt"));
			v.add(new FileInputStream("3.txt"));

			Enumeration<FileInputStream> en = v.elements();

			SequenceInputStream sis = new SequenceInputStream(en);

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

			byte[] buf = new byte[1024];

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

			fos.close();
			sis.close();
		}
	}

十七、IO流——切割文件

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

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

		//切割文件
		public static void splitFile() throws IOException 
		{
			FileInputStream fis = new FileInputStream("123.mp3");

			FileOutputStream fos = null;
			
			byte[] buf = new byte[1024*1024];

			int len=0, count=1;

			while((len=fis.read(buf))!=-1)
			{
				fos = new FileOutputStream(count+".part");
				count++;
				fos.write(buf,0,len);
				fos.close();
			}
			fis.close();
		}
		
		//文件合并
		public static void merge() throws IOException 
		{
			ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

			for (int x=1 ;x<=3 ;x++ )
			{
				al.add(new FileInputStream(x+".part"));
			}

			final Iterator<FileInputStream> it = al.iterator();

			Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
			{
				public boolean hasMoreElements()
				{
					return it.hasNext();
				}
				public FileInputStream nextElement()
				{
					return it.next();
				}
			};

			SequenceInputStream sis = new SequenceInputStream(en);

			FileOutputStream fos = new FileOutputStream("111.mp3");

			byte[] buf = new byte[1024];

			int len = 0;

			while((len=sis.read(buf))!=-1)
			{
				fos.write(buf,0,len);
			}
			fos.close();
			sis.close();
		}
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值