黑马程序员--IO(Java)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一.IO流

1.用于处理设备上数据。(IO流用来处理设备之间的数据传输)
用到IO流时,写代码要导包import java.io.*;


2.流也进行分类:
1)、流按流向分为:输入流(读)和输出流(写)。
2)、因为处理的数据不同,分为字节流和字符流。


3.IO流的常用基类:
1)、字节流的抽象基流:InputStream和OutputStream
2)、字符流的抽象基流:Reader和Writer
注:此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能。




二.字符流(Reader和Writer)

1. 字符流只用于处理文字数据(文本文件)。


2.字符流的读写:

(代码 FileWriterDemo.java):

/*
先学习一下字符流的特点。
IO流是用于操作数据的。数据的最常见体现形式是:文件。

需求:在硬盘上,创建一个文件并写入一些文字数据。
在javaAPI文档中找到一个专门用于操作文件的Writer子类对象,FileWriter。
*/
import java.io.*;
class FileWriterDemo 
{
	public static void main(String[] args) throws IOException //读、写都会发生IO异常
	{
		//第一步:
		//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
		//而且该文件会被创建到指定路径下。
		//如果该目录下已有同名文件,将被覆盖。
		//其实该步就是在明确数据要存放的目的地。
		FileWriter fw = new FileWriter("demo.txt");

		//第二步:
		//调用write方法,将字符串写入到流中。
		fw.write("abc");

		//刷新流对象中的缓冲区的数据。将数据刷到目的地中。
		//fw.flush();

		//第三步:
		//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。将数据刷到目的地中。
		//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
		fw.close();


	}
}


(代码 FileWriterDemo2.java):

//IO异常的处理方式。
//创建文件的三步都会发生IO异常。
import java.io.*;
class FileWriterDemo2 
{
	public static void main(String[] args) 
	{
		FileWriter fw = null;
		try
		{
			fw = new FileWriter("k:\\demo.txt");
			fw.write("abcd");
		}
		catch (IOException e)
		{
			System.out.println(e.toString());
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();
			}
			catch (IOException e)
			{
				System.out.println(e.toString());
			}
		}
	}
}


(代码 FileWriterDemo3.java):

//演示对已有文件的续写。
import java.io.*;
class FileWriterDemo3 
{
	public static void main(String[] args) throws IOException
	{
		//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据的续写。
		FileWriter fw = new FileWriter("demo.txt",true);
		fw.write("xxxx\r\nyyy");//注:\r\n代表换行。
		fw.close();
	}
}


(代码 FileReaderDemo.java):

import java.io.*;
class FileReaderDemo 
{
	public static void main(String[] args) throws IOException
	{
		//创建一个文件读取流对象,和指定名称的文件相关联。
		//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException。
		FileReader fr = new FileReader("demo.txt");

		//第一种读取方式:
		//调用读取流对象的read方法。
		//read():一次读一个字符,而且会自动往下读。
		/*
		int ch = 0;
		while((ch=fr.read())!=-1)
		{
			System.out.println((char)ch);
		}
		fr.close();
        */

		//第二种读取方式:
		//通过字符数组进行读取。
		//定义一个字符数组,用于存储读到的字符。
		//read(char[])返回的是读到字符个数。
		char[] buf = new char[1024];
		int num = 0;
		while((num=fr.read(buf))!=-1)
		{
			System.out.println(new String(buf,0,num));
		}
		fr.close();

	}
}


3.练习:
(代码 CopyText.java):

//练习:将c盘的一个文本文件复制到D盘。
/*
步骤:
1,在D盘创建一个文件。用于存储C盘文件中的数据。
2,定义读取流和C盘文件关联。
3,通过不断的读写完成数据存储。
4,关闭资源。
*/
import java.io.*;
class CopyText
{
	public static void main(String[] args) 
	{
		FileWriter fw = null;
		FileReader fr = null;
		try
		{
			fw = new FileWriter("d:\\CopyText_copy.txt");
			fr = new FileReader("c:\\CopyText.txt");
			char[] buf = new char[1024];
			int num = 0;
			while((num=fr.read(buf))!=-1)
			{
				fw.write(buf,0,num);
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("失败");
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("关闭失败");
			}
			try
			{
				if(fr!=null)
					fr.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("关闭失败");
			}
		}
	}
}


 

4.字符流的缓冲区——BufferedReader和BufferedWriter:
 1)、缓冲区的出现是为了提高流的操作效率而出现的。
 所以在创建缓冲区之前,必须要先有流对象。
 (代码 BufferedWriterDemo.java):


 

//字符写入流缓冲区:
import java.io.*;
class BufferedWriterDemo 
{
	public static void main(String[] args) throws IOException
	{
		//创建一个字符写入流对象。
		FileWriter fw = new FileWriter("buf.txt");

		//为了提高字符写入流效率,加入了缓冲技术。
		//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
		BufferedWriter bufw = new BufferedWriter(fw);
        
		bufw.newLine();//该缓冲区中提供了一个跨平台的换行符。
        bufw.write("abcd");
		bufw.flush();//只要用到缓冲区,就要刷新。
		bufw.close();//关闭缓冲区,就是关闭缓冲区中的流对象。
	}
}


(代码 BufferedReaderDemo.java):

//字符读取流缓冲区:
//该缓冲区提供了一个一次读一行的方法readLine,方便于对文本数据的获取。
//当返回null时,表示读到文件末尾。
//readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。
import java.io.*;
class BufferedReaderDemo 
{
	public static void main(String[] args) throws IOException
	{
		//创建一个字符读取流对象和文件相关联。
		FileReader fr = new FileReader("buf.txt");

		//为了提高效率,加入缓冲技术。
		//将字符读取流对象作为参数传递给缓冲区的构造函数。
		BufferedReader bufr = new BufferedReader(fr);

		String line = null;
		while((line=bufr.readLine())!=null)
		{
			System.out.println(line);
		}
		bufr.close();
	}
}


2)、缓冲区技术练习:
(代码 CopyTextBuf.java):

//练习:通过缓冲区技术将c盘的一个文本文件复制到D盘。
import java.io.*;
class CopyTextBuf 
{
	public static void main(String[] args) 
	{
		BufferedReader bufr = null;
		BufferedWriter bufw = null;
		try
		{
			bufw = new BufferedWriter(new FileWriter("d:\\Copy_copy.txt"));
			bufr = new BufferedReader(new FileReader("c:\\copy.txt"));
			String line = null;
			while((line=bufr.readLine())!=null)
			{
				bufw.write(line);
				bufw.newLine();
				bufw.flush();
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("读写失败");
		}
		finally
		{
			try
			{
				if(bufr!=null)
					bufr.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取关闭失败");
			}
			try
			{
				if(bufw!=null)
					bufw.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写入关闭失败");
			}
		}
	}
}


3)、自定义BufferedReader:
(代码 MyBufferedReader.java):

/*
明白了BufferedReader类中的特有方法readLine的原理后,
可以自定义一个类包含一个功能和readLine一致的方法。
来模拟一下BufferedReader。
*/
import java.io.*;
class MyBufferedReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("buf.txt");
		MyBufferedReader m = new MyBufferedReader(fr);
		String line = null;
		while((line=m.myreadLine())!=null)
		{
			System.out.println(line);
		}
		m.myclose();
	}
}
class MyBufferedReader extends Reader
{
	private Reader r;
	MyBufferedReader(Reader r)
	{
		this.r = r;
	}
	public String myreadLine() throws IOException
	{
		//定义一个临时容器。原BufferedReader封装的是字符数组。
		//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
		StringBuilder sb = new StringBuilder();
		int ch = 0;
		while((ch=r.read())!=-1)
		{
			if(ch=='\r')
				continue;
			if(ch=='\n')
				return sb.toString();
			else
				sb.append((char)ch);
		}
		if(sb.length()!=0)
			return sb.toString();
		return null;
	}
    public void myclose() throws IOException
	{
		r.close();
	}

	//复写父类Reader中的抽象方法.
    public int read(char[] cbuf, int off, int len) throws IOException  
    {  
        return r.read(cbuf,off,len);  
    }  
  
    //复写父类Reader的close方法.
    public void close()throws IOException  
    {  
        r.close();  
    }  
}


装饰设计模式:(上面讲到的MyBufferedReader的例子就是最好的装饰设计模式的例子。)
当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能。那么自定义的类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,通过更强的功能。


装饰与继承区别:
装饰模式比继承要灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。所以装饰类和被装饰类通常属于同一个体系。


4)、LineNumberReader:
在BufferedReader中有个直接的子类LineNumberReader,其中有特有的方法获取和设置行号。当然它也有readLine方法。
setLineNumber(); 设置初始行号
getLineNumber(); 获取行号



三.字节流(InputStream 输入流(读)和 OutputStream 输出流(写))

1.基本操作与字符流类相同。它不仅可以操作字符,还可以操作其他媒体文件。


2.由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。


3.字节流读写:
(代码 FileStream.java):

/*
需求:想要操作图片数据,这时就要用到字节流。

InputStream特有方法:
int available();返回文件中的字节个数
注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。
但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。
当文件过大时,此数组长度所占内存空间就会溢出。
所以,此方法慎用,当文件不大时,可以使用。
*/
import java.io.*;
class FileStream
{
	public static void main(String[] args) throws IOException
	{
		//writeFile();
		//readFile_1();
		//readFile_2();
		readFile_3();
	}
	public static void writeFile() throws IOException
	{
		FileOutputStream fos = new FileOutputStream("fos.txt");
		fos.write("abcde".getBytes());
		fos.close();
	}
	public static void readFile_1() throws IOException
	{
		FileInputStream fis = new FileInputStream("fos.txt");
		int ch = 0;
		while((ch=fis.read())!=-1)
		{
			System.out.println((char)ch);
		}
		fis.close();
	}
	public static void readFile_2() throws IOException
	{
		FileInputStream fis = new FileInputStream("fos.txt");
		byte[] buf = new byte[1024];
		int num = 0;
		while((num=fis.read(buf))!=-1)
		{
			System.out.println(new String(buf,0,num));
		}
		fis.close();
	}
	public static void readFile_3() throws IOException
	{
		FileInputStream fis = new FileInputStream("fos.txt");
		//定义一个刚刚好的缓冲区,不用再循环了。
		byte[] buf = new byte[fis.available()];
		fis.read(buf);
		System.out.println(new String(buf));
		fis.close();
	}
}


4.练习:
(代码 CopyPic.java):

/*
练习:复制一个图片。
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
*/
import java.io.*;
class CopyPic 
{
	public static void main(String[] args) 
	{
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try
		{
			fos = new FileOutputStream("1_copy.JPG");
			fis = new FileInputStream("1.JPG");
			byte[] buf = new byte[1024];
			int num = 0;
			while((num=fis.read(buf))!=-1)
			{
				fos.write(buf,0,num);
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("读写失败");
		}
		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("写入关闭失败");
			}
		}
	}
}


5.字节流的缓冲区:
同样是提高了字节流的读写效率(BufferedInputStream和BufferedOutputStream)。

read():会将字节byte型提升为int型。
write():会将int型强转为byte型。



四.读取键盘录入

1.标准输入输出流:
System.in:对应的标准输入设备,键盘。
System.out:对应的是标准的输出设备,控制台。


2.键盘录入练习:(用到转换流)
(代码 ReadIn.java):

/*
需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。
*/
/*
转换流:
当使用输入流进行键盘录入时,只能一个字节一个字节进行录入。
为了提高效率,可以自定义一个数组将一行字节进行存储。
当一行录入完毕,再将一行数据进行显示。这种正行录入的方式,和字符流读一行数据的原理是一样的。也就是readLine方法。
那么能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中方法。而键盘录入的read方法是字节流InputStream的方法。
那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?这就需要用到转换流了。
*/
import java.io.*;
class ReadIn 
{
	public static void main(String[] args) throws IOException
	{
		/*
		InputStream in = System.in;
		StringBuilder sb = new StringBuilder();
		while(true)
		{
			int ch = in.read();
			if(ch=='\r')
				continue;
			if(ch=='\n')
			{
				String s = sb.toString();
				if("over".equals(s))
					break;
				System.out.println(s.toUpperCase());
				sb.delete(0,sb.length());
			}
			else
				sb.append((char)ch);
		}
		*/
		
		//转换流:
		//获取键盘录入对象。
		InputStream in = System.in;
		//将字节流对象转成字符流对象,使用转换流InputStreamReader。
		InputStreamReader isr = new InputStreamReader(in);
		//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader。
		BufferedReader bufr = new BufferedReader(isr);

		OutputStream out = System.out;
		OutputStreamWriter osw = new OutputStreamWriter(out);
		BufferedWriter bufw = new BufferedWriter(osw);

		String line = null;
		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			//System.out.println(line.toUpperCase());
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
	}
}


 

五.流的操作规律

1.通过三个明确来完成。

1)、明确源和目的。
源:输入流。InputStream 和 Reader。
目的:输出流。OutputStream 和 Writer。
2)、操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3)、当体系明确后,再明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘,键盘。
目的设备:内存,硬盘,控制台。


例子:
需求:将键盘录入的数据保存到一个文件中。
      1)、源:InputStream和Reader
             是不是纯文本?是!Reader
             设备:键盘。对应的对象是System.in。
             既然明确了Reader,那么就将System.in转换成Reader。用Reader体系中转换流,InputStreamReader。
             InputStreamReaderisr = new InputStreamReader(System.in);
             需要提高效率吗?需要,BufferedReader
             BufferedReaderbufr = new BufferedReader(isr);
      2)、目的:OutputStream和Writer
               是否是存文本?是!Writer。
               设备:硬盘。一个文件。使用 FileWriter。
               FileWriter fw = newFileWriter("c.txt");
               需要提高效率吗?需要。BufferedWriter
               BufferedWriter bufw = new BufferedWriter(fw);


2.转换流特有功能:转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符。
转换流什么时候使用:字符和字节之间的桥梁。通常,涉及到字符编码转换时,需要用到转换流。
转换流的应用:字节流中的数据都是字符时,转成字符流操作更高效。


3.在代码开头,通过System类的setIn,setOut方法可以对默认设备进行改变。
System.setIn(newFileInputStream(“1.txt”)); 将源改成文件1.txt。
System.setOut(newFileOutputStream(“2.txt”)); 将目的改成文件2.txt



六. File类

1.理解:
将文件系统中的文件和文件夹封装成了对象。提供了更多的属性和行为可以对这些文件和文件夹进行操作。这些是流对象办不到的,因为流只操作数据。


2.File对象创建:
(代码 FileDemo.java):

//File对象创建:
import java.io.*;
class FileDemo 
{
	public static void main(String[] args) 
	{
		consMethod();
	}
	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.separator表示目录分隔符,可以跨平台使用。
		File f4 = new File("c:"+File.separator+"abc"+File.separator+"d.txt");
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}

}


3.File类常见方法:

1)、创建:
boolean createNewFile():在指定目录下创建文件,如果该文件已存在,则不创建。而对操作文件的输出流而言,输出流对象已建立,就会创建文件,如果文件已存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。

2)、删除:
boolean delete():删除文件或目录。文件存在,返回true;文件不存在或者正在被执行,返回false。 
void deleteOnExit():在虚拟机退出时删除。
注意:在删除文件夹时,必须保证这个文件夹中没有任何内容,才可以将该文件夹用delete删除。

3)、判断:
boolean exists():判断文件或者文件夹是否存在。
boolean isFile():是否是文件。
boolean isDirectory():是否是文件夹。
boolean isHidden():是否是隐藏文件。
boolean isAbsolute():文件是否是绝对路径。即使文件不存在,也可以判断。

4)、获取信息:
String getPath():获取文件的相对路径(即创建的对象传入的参数是什么就获取到什么)。
String getAbsolutePath():获取文件的绝对路径。
String getParent():获取文件父目录。返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。
long length():获取文件大小。
String getName():获取文件名。

5)、重命名:
boolean renameTo(File dest):可以实现移动的效果。剪切+重命名。

6)、列出文件及文件过滤:
File[] listRoots():列出可用的文件系统根目录,即系统盘符。
String[] list():列出指定目录下的当前的文件和文件夹的名称。包含隐藏文件。
File[] listFiles():获取当前文件夹下的所有文件和文件夹。
list与listFiles区别:list返回的是一个字符串数组;listFiles返回的是一个抽象路径名数组。


File类方法代码演示:
(代码 FileDemo2.java):

//File类常见方法演示:
import java.io.*;
class  FileDemo2
{
	public static void main(String[] args) throws IOException
	{
		//method_1();
		//method_2();
		method_3();
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void method_1() throws IOException
	{
		File f = new File("file.txt");
		sop("create:"+f.createNewFile());
		sop("delete:"+f.delete());
	}
	public static void method_2() throws IOException
	{
		File f = new File("file.txt");
		f.createNewFile();
		sop("exists:"+f.exists());
		//记住:在判断文件对象是否是文件或者文件夹(目录)时,
		//必须要先判断该文件对象封装的内容是否存在。
		//通过exists判断。
		sop("dir:"+f.isDirectory());
		sop("file:"+f.isFile());
	}
	public static void method_3() throws IOException
	{
		File f = new File("file.txt");
		sop("path:"+f.getPath());
		sop("absPath:"+f.getAbsolutePath());
		sop("parent:"+f.getParent());//该方法返回的是绝对路径中的父目录。
	}
}


(代码 FileDemo3.java):

//列出该目录下的所有文件或者.java的文件。
import java.io.*;
class FileDemo3 
{
	public static void main(String[] args) 
	{
		File dir = new File("C:\\Users\\Administrator\\Desktop\\GUI");
		//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
		//FilenameFilter:文件名过滤器,是一个接口,其中包含一个方法,accept(File dir,String name),返回的是boolean型,对不符合条件的文件过滤掉。
		String[] arr = dir.list(new FilenameFilter()
		{
			public boolean accept(File dir,String name)
			{
				return name.endsWith(".java");
			}
		});
		for(String name : arr)
		{
			System.out.println(name);
		}
	}
}


(代码 FileDemo4.java):

/*
列出指定目录下文件或者文件夹,包含子目录中的内容。
也就是列出指定目录下所有内容。
*/
import java.io.*;
class FileDemo4 
{
	public static void main(String[] args)
	{
		File f = new File("C:\\Users\\Administrator\\Desktop\\GUI");
		q(f);
	}
	public static void q(File f)
	{
		System.out.println(f);
		File[] arr = f.listFiles();
		for(int x=0;x<arr.length;x++)
		{
			if(arr[x].isDirectory())
				q(arr[x]);
			else
				System.out.println(arr[x]);
		}
	}
}
/*
此题用到递归:
当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。
这种表现形式,或者编程手法,称为递归。
递归注意事项:
1,限定条件。
2,注意递归的次数,尽量避免内存溢出。
什么时候用递归呢?
当一个功能被重复使用,而每一次使用该功能时的参数不确定,都由上次的功能元素结果来确定。
*/


(代码 FileDemo5.java):

/*
删除一个带内容的目录。
*/
import java.io.*;
class FileDemo5 
{
	public static void main(String[] args) 
	{
		File f = new File("C:\\Users\\Administrator\\Desktop\\1");
		del(f);
	}
	public static void del(File f)
	{
		File[] arr = f.listFiles();
		for(int x=0;x<arr.length;x++)
		{
			if(arr[x].isDirectory())
				del(arr[x]);
			else
				System.out.println(arr[x].toString()+"-file-"+arr[x].delete());
		}
		System.out.println(f+"-dir-"+f.delete());
	}
}


(代码 FileDemo6.java):

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

思路:
1,对指定的目录进行递归。
2,获取递归过程中所得的java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。
*/
import java.io.*;
import java.util.*;
class FileDemo6 
{
	public static void main(String[] args) throws IOException
	{
		File f = new File("C:\\Users\\Administrator\\Desktop\\GUI");
		List<File> list = new ArrayList<File>();
		fileToList(f,list);//把路径写到集合。
		File f2 = new File(f,"f2.txt");
		writeToFile(list,f2);//把集合存到文件中。
	}
	public static void fileToList(File f,List<File> list)
	{
		File[] arr = f.listFiles();
		for(int x=0;x<arr.length;x++)
		{
			if(arr[x].isDirectory())
				fileToList(arr[x],list);
			else
			{
				if(arr[x].getName().endsWith(".java"))
					list.add(arr[x]);
			}

		}
	}
	public static void writeToFile(List<File> list,File f2) throws IOException
	{
		BufferedWriter bufw = new BufferedWriter(new FileWriter(f2));
		for(File name : list)
		{
			bufw.write(name.getAbsolutePath());
			bufw.newLine();
			bufw.flush();
		}
		bufw.close();
	}
}


 

七. Properties类

1.理解:
Properties是Hashtable的子类,它具备Map集合的特点。是集合中和IO技术想结合的集合容器。(因为Properties是集合,所以写代码时需要导包import java.util.*;)


2.特点:
1)、可以持久化存储数据。
2)、键值都是字符串。
3)、一般用于配置文件。


3.Properties类的特有方法:
load():将流中的数据加载进集合。
list():将集合的键值数据列出到指定的目的地。
store():写入各个项后,刷新输出流(将流中的数据更改)。
(代码 PropertiesDemo.java):

import java.io.*;
import java.util.*;
class PropertiesDemo 
{
	public static void main(String[] args) throws IOException
	{
		//setAndGet();
		//method_1();
		loadDemo();
	}
	//设置和获取元素。
	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");//指定key获取value。
		//System.out.println(value);

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

		//返回属性列表的键集,存入Set集合.
		Set<String> names = prop.stringPropertyNames();
		for(String s : names)
		{
			System.out.println(s+":"+prop.getProperty(s));
		}
	}

	//演示,如何将流中的数据存储到集合中。
	/*
	将info.txt中的键值数据存到集合中进行操作。
	1,用一个流和info.txt文件关联。
	2,读取一行数据,将该行数据用“=”进行切割。
	3,等号左边作为键,右边作为值。存到Properties集合中即可。
	*/
	public static void method_1() throws IOException
	{
		BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
		Properties prop = new Properties();
		String line = null;
		while((line=bufr.readLine())!=null)
		{
			String[] arr = line.split("=");
			prop.setProperty(arr[0],arr[1]);
		}
		bufr.close();
		System.out.println(prop);
	}
	//将流中的数据存储到集合中。使用Properties的特有方法load。
	public static void loadDemo() throws IOException
	{
		FileInputStream fis = new FileInputStream("info.txt");
		Properties prop = new Properties();
		prop.load(fis);//将流中的数据加载进集合。
		
		//更改流中的数据。
		prop.setProperty("lisi","100");
		FileOutputStream fos = new FileOutputStream("info.txt");
		prop.store(fos,"haha");//将属性列表(键值对)写入输出流。haha是属性列表的描述。

		//System.out.println(prop);
		prop.list(System.out);//将集合的键值数据列出到指定的目的地。
		fis.close();
		fos.close();
	}
}


4.练习:
(代码 PropertiesDemo2.java):

//练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示.
//要建立一个配置文件,用于记录该软件的使用次数。
//该配置文件使用键值对的形式。键值对数据是map集合。数据是以文件形式存储。使用io技术。那么map+io-->Properties。 
import java.io.*;
import java.util.*;
class  PropertiesDemo2
{
	public static void main(String[] args) throws IOException 
	{
		Properties prop = new Properties();
		File f = new File("count.ini");
		if(!f.exists())
			f.createNewFile();
		FileInputStream fis = new FileInputStream(f);
		prop.load(fis);//加载流中的文件数据到集合中.
		int count = 0;
		String value = prop.getProperty("time");
		if(value!=null)
		{
			//将集合中的值value(value是以字符串形式存在),转成int型的,然后赋值给count。
			count = Integer.parseInt(value);
			if(count>=5)
			{
				System.out.println("使用次数已到");
				return ;
			}
		}
		count++;
		prop.setProperty("time",count+"");
		FileOutputStream fos = new FileOutputStream(f);
		prop.store(fos,"");//将集合中的数据存入硬盘文件中.
		fis.close();
		fos.close();
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值