java基础之 IO系统



第一讲、IO流概述基本知识
IO流:
用来处理设备之间数据传输,java中对数据的操作是通过流进行的,java用于操作流的对象都在IO包中,
流按操作可以分为两种:字节流和字符流。按流向分:输入流和输出流。
IO流常用基类:
字节流抽象基类: InputSteam  OutputStream
字符流抽象基类: Reader Writer
这四个类派生的子类的名字都是以其父类名字为子类的后缀。例如:
InputStream的子类:FileInputStream   Reader的子类:FileReader
字符流:
以一个文本文件操作为例,通过API查找,找到了用于操作文件的Writer子类对象FileWriter.
创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件,而且该文件会被创建在制动目录下。
如果已有同名文件将被覆盖。
flush和close的区别:flush刷新后流还可以继续使用,但是close刷新以后就关闭了流。

实例代码:

import java.io.*;
class FileWriterDemo 
{
	public static void main(String[] args) throws IOException
	{
		//创建对象。
		FileWriter fw=new FileWriter("demo.txt");
		//调用write方法,将字符串写入到流中
		fw.write("asdfasfds");
		//刷新流对象中的缓冲数据。
		//将数据刷到目的地中
		//fw.flush();
		//关闭此数据流但是先要刷新一次
		fw.close();
	}
}
IO异常的处理方式:
因为IO要操作的是磁盘的文件,所以一定会产生异常,需要try——catch语句。
FileWriter fw = null;语句在外面建立引用,在try内初始化,这样fw就可以作用
整个函数。关闭资源要写在finally语句中,但是如果不加try语句,则会抛出IOException
异常,如果指定的文件路径不存在,fw对象就不会创建,此时fw=null;在调用close
方法时就会报空指针异常。

import java.io.*;
/*IO的异常处理方式*/
class FileWriterDemo2 {
	public static void main(String[] args) {
		//外部创建引用,fw可以作用于整个函数
		FileWriter fw=null;
		try{
			fw=new FileWriter("demo.txt");
			fw.write("asdfasgghadfsd");
		}
		catch (IOException e){
			System.out.println(e.toString());
		}
		finally{
			try{//解决空指针异常
				if(fw!=null)
				fw.close();
			}
			catch (IOException e){
				System.out.println(e.toString());
			}			
		}
	}
}
对已有文件数据进行续写:
在API中找到FileWriter(String fileName, boolean append) 方法,根据给定的文件名
以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
如果为 true,则将数据写入文件末尾处,而不是写入文件开始处。 
抛出异常IOException:
如果指定文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;
抑或因为其他某些原因而无法打开它 
实例代码:

import java.io.*;
//对已有文件的数据续写,
class FileWriterDemo3{
	public static void main(String[] args) {
		//外部创建引用
		FileWriter fw=null;
		try{
			//传递一个true参数,代表不覆盖已有文件并
			//在以有文件末尾处进行续写			
			fw=new FileWriter("demo.txt",true);
			//换行,
			fw.write("\r\n45454545");
		}
		catch (IOException e){
			System.out.println(e.toString());
		}
		finally{
			try{
				if(fw!=null)
				fw.close();
			}
			catch (IOException e){
				System.out.println(e.toString());
			}			
		}
	}
}
字符文件读取:FileReader,需要先关联一个已经存在的文件,如果不存在发生异常,FileNotFoundException
FileReader下面也有close方法,但是该方法不刷新,此外还有读一个和读数组的方法read,该方法可以自动往下读,
读到末尾就返回-1,因此可以用-1作为循环读取结束的标志。此外read方法还可以以数组方式读取,
实例代码:
1.单个字符读取

import java.io.*;
class  FileReaderDemo{
	public static void main(String[] args) {
		//外部创建引用,可以作用于整个函数
		FileReader fr=null;
		try{//创建一个文件读取流对象,和指定名称文件关联保证该文件是存在的,如果不存在发生异常,
			fr=new FileReader("demo.txt");			
			int ch=0;
			//读到最后如果没有则返回-1
			while((ch=fr.read())!=-1){
				System.out.println((char)ch);
			}
		}
		catch (IOException e){
			System.out.println(e.toString());
		}
		finally{
			try{
				fr.close();
			}
			catch (IOException e){
				System.out.println(e.toString());
			}			
		}
	}
}
2.以数组方式读取:

/*第二种读取方式:通过字符数组进行读取。
read(char[] cbuf, int offset, int length) 
将字符读入数组中的某一部分。*/
import java.io.*;
class  FileReaderDemo2{
	public static void main(String[] args) {
		FileReader fr=null;
		//定义一个数组,用于存储读取到的字符。
		//该read(char[])返回的是读到字符个数。
		char[] buf=new char[6];		
		try{
			if(fr!=null)
			System.out.println(new String(buf));
		}
		catch (FileNotFoundException e){
			System.out.println(e.toString());
		}
		finally{
			try{
				if(fr!=null)
				fr.close();
			}
			catch (IOException e){
				System.out.println(e.toString());
			}
		}
	}
}
复制文件:其实就是将C盘下的文件数据存储到D盘的一个文件中 
步骤:
1.在D盘创建一个文件用于存储C盘文件中的数据。
2.定义读取流和C盘文件关联。
3.通过不断的读写完成数据存储。
4.关闭资源。
代码实例:

package IOSystem;
import java.io.*;
public class CopyTextDemo {
	public static void main(String[] args) {
		Copy();
	}
private static void Copy() {
	FileReader fr = null;
	FileWriter fw = null;
	try {
		//源和目的
		fr = new FileReader("SystemDemo.txt");
		fw = new FileWriter("F:\\C#Data\\come.txt");
		//缓冲区
		char[] buf = new char[1024];
		int len = 0;
		//循环读写,直到返回—1
		while((len = fr.read(buf))!=-1){
			fw.write(buf,0,len);
		}
	} catch (Exception e) {
		// TODO: handle exception
		throw new RuntimeException("读写失败");
	}
	finally{
		if(fr!=null)
		try {
				fr.close();
		} catch (Exception e2) {
			System.out.print(e2.toString());
		}
		if(fw!=null)
			try {
				fw.close();
			} catch (Exception e2) {
				System.out.print(e2.toString());
			}
		}
	}
}
第二讲 缓冲区读写及其他
字符流缓冲区:提高了对数 据的读写效率,对应类BufferedReader和BufferedWriter,缓冲区
要结合流才可以使用,在流的基础上对流的功能进行了增强。
注意:只要用到缓冲技术就要对缓冲区进行刷新操作。关闭缓冲区就是关闭缓冲区流对象。
缓冲区提供了一个跨平台换行方法:newLine();
下面通过缓冲区技术演示字符流和字节流读写的两个综合实例。
字符流缓冲区读写实例代码:

/*通过缓冲区复制一个。Java文件*/
import java.io.*;
class  CpTextBuf{
	public static void main(String[] args) {
		//外部创建引用,可以作用于整个函数
		BufferedReader bufr=null;
		BufferedWriter bufw=null;
		try{
			//关联源和目的
			bufr=new BufferedReader(new FileReader("BufferedWriterDemo.java"));
			bufw=new BufferedWriter(new FileWriter("BufferedTextCp.txt"));
			String line=null;
			//整行读取,直到返回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("写关闭失败");
			}
		}
	}
}
字节流缓冲区读取:使用字节流操作对象的FilterInputStream的子类BufferedInputStream和
FilterOutputStream的子类BufferedOutputStream
下面以复制一个磁盘的MP3文件为例
代码:

import java.io.*;
class  CopyMp3{
	public static void main(String[] args) throws IOException{
		//统计代码运行时间
		long start=System.currentTimeMillis();
		copy_1();
		long end=System.currentTimeMillis();
		System.out.println((end-start)+"毫秒");
	}
	//通过字节流的缓冲区完成复制
	public static void copy_1()throws IOException{
		//关联源和目的
		BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("f:\\1.mp3"));
		BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("e:\\紫金花园.mp3"));
		int by=0;
		//-1为结束循环标志
		while((by=bufis.read())!=-1){
			bufos.write(by);
		}
		bufos.close();
	}
}
readLine原理:无论读一行还是读多个,最终都是从磁盘中一个一个的读取,也就是read方法,只不过是把
回车符号前面读到的数据临时存储一下,所以效率稍高。
装饰设计模式:
当想要对已有的对象进行功能增强时,可以定义一个类将已有对象传入,基于已有对象的功能
并提供加强功能,那么自定义的该类就称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象提供更强大功能。
装饰类避免了继承体系的臃肿,与被装饰类属于同一个体系中,
例如BufferedReader和readLine,代码实例:

package IOSystem;
public class ZhuangShiLeiDemo {
	public static void main(String[] args) {
		SuperPerson sp = new SuperPerson();
		sp.Superchifan();
	}
}
class Person{
	public void chifan(){
		System.out.println("吃饭");
	}
}
//装饰类
class SuperPerson{
	private Person p;
	//装饰吃饭这个功能
	SuperPerson(){
		this.p=p;
	}
	public void Superchifan(){
		System.out.println("开胃酒");
		System.out.println("吃饭");
		System.out.println("甜点");
		System.out.println("散步");
	}
}
使用LineNumberReader方法读取一个文本文件打印在控制台,并带行号。

代码:

package IOSystem;
import java.io.*;
public class LineNumberReaderDemo {
/*
 * 获取一个文件中的内容并打印在控制台带行号。
 * */
	public static void main(String[] args) {
		FileReader fr = null;
		LineNumberReader lnr = null;
		try {
			//关联文件
			fr = new FileReader("D:\\java0217\\day19\\CopyPic.java");
			lnr = new LineNumberReader(fr);
			String line = null;
			//设置行号从100开始
			lnr.setLineNumber(100);
			while((line = lnr.readLine())!= null){
				System.out.println(lnr.getLineNumber()+": "+line);
			}
		} catch (Exception e) {
			// TODO: handle exception
			throw new RuntimeException("读写失败");
		}
		finally{
			if(fr != null)
				try {
					lnr.close();					
				} catch (Exception e2) {
					// TODO: handle exception
					throw new RuntimeException("关闭失败");
				}
		}
	}

}
实例演示写文本文件和三种读文件方法,其中定义缓存数组的方法有byte[]buf=new byte[fis.available()];
同时字节流中有一个特有的方法,byte[]buf=new byte[fis.available()];创建一个刚刚好的数组,不用循环
但是操作的数据大小受限,所以一般还是使用1024整数倍创建数组。
代码:

import java.io.*;
class  FileStream{
	public static void main(String[] args) throws IOException{
		readFile_3();
		//readFile_2();
		//readFile_1();
		//writeFile();
	}	
	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();
	}
	public static void readFile_2()throws IOException{
		FileInputStream fis=new FileInputStream("fos.txt");
		byte[] buf=new byte[1024];
		int len=0;
		//整行读取
		while((len=fis.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
		fis.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 writeFile() throws IOException{
		//创建文件输出流
		FileOutputStream fos=new FileOutputStream("fos.txt",true);
		//写字符到已关联的文件对象(以默认编码方式)
		fos.write("abcde".getBytes());
		fos.close();
	}
}
通过键盘录入一行数据并大写类似于读一行数据原理也就是
readLine方法
readLine方法是字符流BufferedReader类中的方法
而键盘录入的read方法时字节流InputStream的方法
能不能将字节流转换成字符流再使用字符缓冲区的readLine
方法呢?
此时我们可以用InputStreamReaer将字节流转换成字符流并使用readLine方法录入,
同时使用OutputStreamWriter将输出字节流转成字符流进行行输出,下面通过实例
来体现。
代码:整行读取一个文本文件内容,并进行大写转换后在控制台输出。

import java.io.*;
class  TransStreamDemo2{
	public static void main(String[] args) throws IOException{
		/*//获取键盘录入对象
		InputStream in=System.in;
		//将字节流对象转换成字符流对象,使用InputStreamReader
		InputStreamReader isr=new InputStreamReader(in);
 
		//为了提高效率,将字符串进行缓冲区技术高效操作使用
		//BufferedReader
		BufferedReader bufr=new BufferedReader(isr);*/		
		//键盘录入一行,最常见写法
		BufferedReader bufr=
			new BufferedReader(new InputStreamReader(new FileInputStream("out.txt")));	
		/*OutputStream out=System.out;
		OutputStreamWriter osw=new OutputStreamWriter(out);
		BufferedWriter bufw=new BufferedWriter(osw);*/
		//键盘输出一行,最常见写法
		BufferedWriter bufw=
			new BufferedWriter(new OutputStreamWriter(System.out));
		String line=null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();//换行,跨平台性。
			bufw.flush();
		}
		bufr.close();
	}
}
IO流操作规律总结:
流操作基本规律:
两个明确:
1.源和目的。
源:输入流。InputStream Reader
目的:输出流.OutputStream Writer
2.操作的数据是否是纯文本。
是:字符流 Reader Writer
不是:字节流 InputStream OutputStream
3.当体系明确后再明确要使用那个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
例如.将一个文本文件内容存储到另一个文件  复制
源:因为是源所以选用读取流 。InputStream Reader
是不是操作文本文件
是:选择Reader
接下来明确要使用体系中那个对象。
明确设备:硬盘文件。
Reader体系中可以操作文件的对象时FileReader
是否需要提高效率:是:加入Reader体系中缓冲区BufferedReader.
FileReader fr=new FileReader("a.txt");
BufferedReader bufr=new BufferedReader(fr);
目的:OutputStream Writer
是否纯文本。
是:Writer
设备:硬盘文件。
Writer体系中可以操作文件的对象FileWriter
如果提高效率则加入缓冲区;BufferedWriter
扩展:想要把录入的数据按照指定的编码表(utf-8),将数据存入到文件中。
目的:OuputStream Writer
是否是纯文本:是 Writer
设备:硬盘,一个文件。使用FileWriter
但是FileWriter使用的是默认的GBK编码。
但是存储时要指定(utf-8)编码,而只有转换流才可以指定编码表。
所以要使用的对象是OutputStreamWriter。
而该转换流对象要接收一个字节输出流,而且还是可以操作文件输出字节数出流 :FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c:\\hello.java"),"UTF-8");
//需要缓冲的话:
BufferedWriter bufw = new BufferedWriter(osw);
/*转换流什么时候用:字节和字符之间的桥梁,当需要字符编码转换时,需要用到转换流*/
下面代码实例:

class  TransStreamDemo2{
	public static void main(String[] args) throws IOException{		
		//键盘录入一行,最常见写法
		BufferedReader bufr=
			new BufferedReader(new InputStreamReader(System.in));		
		//键盘输出一行,最常见写法
		BufferedWriter bufw=
			new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out.txt"),"UTF-8"));
		//BufferedWriter bufw=
			//new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out.txt"),"GBK"));
		String line=null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
	}
}
日志文件:用于在程序运行时,将程序产生的异常信息保存到一个异常信息文件中,以便于开发者日后查看
解决问题。
示例代码:

import java.io.*;
import java.util.*;
import java.text.*;
class  ExceptionInfo{
	public static void main(String[] args) throws IOException{
		try{
			//自己搞一个角标越界
			int [] arr=new int[2];
			System.out.println(arr[3]);
		}
		catch (Exception e){
			try{
				Date d=new Date();
				//定义时间格式
				SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");			
				String s=sdf.format(d);
				//创建日志文件
				PrintStream ps=new PrintStream("exception.log");
				//现将日期信息写入到日志文件。
				ps.println(s);
				//设置标准输出改为文件对象,
				System.setOut(ps);			
			}
			catch (IOException ex){
				throw new RuntimeException("日志文件创建失败");
			}//如果日志文件创建成功就将异常信息输出到标准输出,(已改为文件对象)
			e.printStackTrace(System.out);
		}
	}
}
第三讲、File类
File类:用来将文件或者文件夹封装成对象。
方便对文件或者文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数。
创建对象方法
File f1=new File("a.txt");
File f2=new File("e:\\abc","b.txt");
File d=new File("e:\\ABD");
File f3=new File(d,"c.txt");
File f4=new File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"d.txt");
separator方法表示用来跨平台的分隔符。
下面介绍了File类的常用方法:
File f1=new File("e:"+File.separator+"a.txt");
//创建文件
sop("creat: "+f1.createNewFile());
//删除文件成功为true,否则false
sop("delete:"+"e:\\a.txt"+f1.delete());
//JVM退出时删除文件,一般用于删除临时性的文件。
f1.deleteOnExit();
//判断文件是否存在
boolean f1.exists() 
          测试此抽象路径名表示的文件或目录是否存在。 存在返回true
//创建文件夹当且仅当已创建目录时,返回 true;否则返回 false 
File dir = new File("e:\\javaData");
sop("mkdir:"+dir.mkdir());
//创建多级目录mkdirs,用法与mkdir类似
isDirectory();isFile()在判断之前必须判断该文件对象是否存在,通过exists()
获取信息:getPath() getName(); lastModified(); 
getParent();该方法返回的是绝对路径中的父目录。如果获取的是相对路径返回null
如果存在上一层目录,则返回该目录。
list();方法。public String[] list()返回一个字符串数组,这些字符串指定此抽象路径名
表示的目录中的文件和目录。指定的文件对象必须是一个目录,而且该目录还必须存在。 
list public String[] list(FilenameFilter filter),文件过滤。
文件过滤代码实例:

import java.io.*;
class FileDemo02 {
	public static void main(String[] args) {
		listDemo_2();
	}
	public static void listDemo_2(){
		//指定一个目录
		File dir=new File("d:\\java0217\\day18");
		//文件过滤器使用   记住喽!!!
		String [] arr=dir.list(new FilenameFilter()
			{
			public boolean accept(File dir,String name)
				{
					return name.endsWith(".bak");
				}
			});
		System.out.println("len:"+arr.length);
		for(String name:arr){//打印.bak文件名
			System.out.println(name);
		}
	}
}
列出指定目录下的所有文件以及文件夹名称。
递归调用要注意:1.限定条件。 2.注意次数,尽量避免内存溢出
示例代码:

package IOSystem;
import java.io.*;
public class FileListDemo {
/*列出制定目录下文件或者文件夹。包含子目录中内容
也就是流出指定目录下所有内容*/
	public static void main(String[] args) {
		File dir = new File("d:\\java0217");
		showDir(dir,0);
	}
	private 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();
		for(int x=0;x<level;x++)
		{
			sb.append("  ");
		}
		return sb.toString();
	}
}
列出一个指定路径下的所有的.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:\\java0217");
		//定义一个File类型的list集合
		List<File> list=new ArrayList<File>();
		//将指定目录下的文件名存入到集合中
		fileToList(dir,list);
		//指定一个文件。目的
		File file=new File(dir,"javalist.txt");
		//将集合中的文件名信息写入到指定的文件
		writeToFile(list,file.toString());
		//打印该集合的长度
		System.out.println(list.size());
	}
	public static void fileToList(File dir,List<File> list)
		{//需要传入目录和集合,因为要递归所以最好是在外部建立集合传入
		//获取路径下的所有文件对象,存入到File类型的数组中
		File[] files = dir.listFiles();
		//遍历数组
		for(File file : files)
		{//如果是目录就递归
			if(file.isDirectory())
				fileToList(file,list);
			else
			{//如果不是目录则获取以.java为扩展名的文件并存入到list集合
				if(file.getName().endsWith(".java"))
					list.add(file);
			}
		}
	}
	public static void writeToFile(List<File>list,String javaListFile)throws IOException
	{//该方法需要传入一个File类型的集合和一个文件目的
		BufferedWriter bufw=null;
		try
		{//关联传入的文件目的
			bufw=new BufferedWriter(new FileWriter(javaListFile));
			for(File f:list)//遍历这个File类型的集合
			{//获取每个.java为扩展名的文件的绝对路径
				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的配置文件,它是用来在一个文件中存储键-值对的,
它提供了几个主要的方法:
1. getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
2. load ( InputStream inStream),从输入流中读取属性列表(键和元素对)。通过对指定的文件(比如说上面的
test.properties 文件)进行装载来获取该文件中的所有键 - 值对。以供 getProperty ( String key) 来搜索。
3. setProperty ( String key, String value) ,调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置
键 - 值对。
4. store ( OutputStream out, String comments),以适合使用 load 方法加载到 Properties 表中的格式,
将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写
入到指定的文件中去。
5. clear (),清除所有装载的 键 - 值对。该方法在基类中提供。
代码实例:

import java.io.*;
import java.util.*;
class  PropertiesDemo{
	public static void main(String[] args) throws IOException{
		loadDemo();
	}
	public static void loadDemo()throws IOException
	{//创建一个Properties类对象
		Properties prop=new Properties();
		//将配置文件关联输入流
		FileInputStream fis=new FileInputStream("info.txt");
		//将流中数据加载进集合
		prop.load(fis);
		//设置键值对
		prop.setProperty("wangwu",60+"");
		//将配置文件关联输出流
		FileOutputStream fos=new FileOutputStream("info.txt");
		//存储修改后的信息
		prop.store(fos,"repair wangwu age");
		//在控制台输出引用其list方法。
		prop.list(System.out);
		fos.close();
		fis.close();
	}
}
配置文件创建使用实例。限定程序运行次数。
代码:

package IOSystem;
//建立一个配置文件,用于记录该软件使用次数,
//这样便于阅读暑促并操作数据
import java.io.*;
import java.util.*;
public 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 ;
			}
		}//如果运行次数不大于或等于5,就将键值对存入到配置文件
		count++;
		prop.setProperty("time",count+"");
		FileOutputStream fos = new FileOutputStream(file);
		prop.store(fos,"");
		fos.close();
		fis.close();
	}
}
第四讲、其他流

打印流:
该流提供了打印方法。可以将各种数据类型的数据都原样打印。
字节打印流:
PrintStream
构造函数可以接受的参数类型:
1.file对象。File(可以直接操作文件)
2.字符串路径,String
3.字节输出流。OutputStream
字符打印流:
PrintWriter
1.file对象。File
2.字符串路径,String
3.字节输出流。OutputStream
4.字符输出流。Writer.
PrintWriter代码例子:

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(流,true);
		//将键盘录入字符自动刷新到文件中
		PrintWriter out=new PrintWriter(new FileWriter("abc.txt"),true);
		String line=null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			out.println(line.toUpperCase());
		}
		out.close();
		bufr.close();
	}
}
合并流:SequenceInputStream将多个流合并成一个流
切割流:SplitFile
下面是切割和合并实例:

import java.io.*;
import java.util.*;
class SplitFile {
	public static void main(String[] args) throws IOException{
		merge();
	}
	//合并************************//
	public static void merge()throws IOException{
		//创建流对象并导入源文件
		ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();
		for(int x=1;x<=4;x++){
			al.add(new FileInputStream("e:\\SplitFiles\\"+x+".part"));
		}
		//对返回的局部变量进行final修饰
		final Iterator<FileInputStream> it = al.iterator();
		//匿名内部类 对返回的局部变量进行final修饰
		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("e:\\zijinhuayuan.mp3");
		byte[] buf=new byte[1024*1024*5];
		int len=0;
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
	//切割*****************************//
	public static void splitFile()throws IOException{
		FileInputStream fis=new FileInputStream("e:\\紫金花园.mp3");
		FileOutputStream fos=null;
		byte[] buf=new byte[1024*1024*3];
		int len=0;
		int count=1;
		while((len=fis.read(buf))!=-1){//指定路径和名字
			fos=new FileOutputStream("e:\\SplitFiles\\"+(count++)+".part");
			fos.write(buf,0,len);
			fos.close();
		}
		fis.close();
	}
}
管道流:PipeInputStream  PipedOutputStream下面的例子演示了管道流读取的方法。

import java.io.*;
//读取管道流
class  Read implements Runnable{//需要传入一个输入流对象
	private PipedInputStream in;
	Read(PipedInputStream in){
		this.in=in;
	}
	public void run(){
		try{//缓存数组接收管道流中的数据
			byte[] buf=new byte[1024];
			System.out.println("暂无数据,读取中******");
			int len=in.read(buf);//返回的是字节数组的长度
			String s=new String(buf,0,len);
			System.out.println(s);
			System.out.println("读到数据,阻塞结束******");
			in.close();
		}
		catch (IOException e){
			throw new RuntimeException("管道读取流失败");
		}
	}
}
//写管道流
class  Write implements Runnable{
	private PipedOutputStream out;
	Write(PipedOutputStream out){
		this.out=out;
	}
	public void run(){
		try{
			System.out.println("开始写入数据,等待中******");
			Thread.sleep(6000);
			out.write("piped comming".getBytes());
			out.close();
		}
		catch (Exception e){
			throw new RuntimeException("管道输出流失败");
		}
	}
}
class PipedStreamDemo{
	public static void main(String[] args) throws IOException{
		//创建读写管道流
		PipedInputStream in=new PipedInputStream();
		PipedOutputStream out=new PipedOutputStream();
		//连接管道流
		in.connect(out);
		//实例化读写并创建线程启动
		Read r=new Read(in);
		Write w=new Write(out);
		new Thread(r).start();
		new Thread(w).start();
	}
}
RandomAccessFile随即访问文件类
该类不是io体系中的子类
而是直接继承的Object。
但是他是io包成员,因为具有读写功能。
内部封装了一个数组,而且通过指针对数组元素进行操作,
可以通过getFilePointer获取指针位置,
同时可以通过seek改变指针位置,
其实完成读写的原理是:内部封装了字节输入和输出流。
通过构造函数可以看出,该类只能操作文件。
该类中常用方法有:
getFilePointer() 返回此文件中的当前偏移量。 
length() 返回此文件的长度。 
int read() 读取一个数据字节和读取一个字节数组。
char readChar() 从此文件读取一个字符。 
int readInt() 读取int型数据         
String readLine() 读取一行
void writeInt(int v) 写入int型数据。
代码演示:

import java.io.*;
class  RandomAccessFileDemo{
	public static void main(String[] args) throws IOException{
		//writeFile();
		readFile();
	}
	public static void readFile()throws IOException{
		//关联随机读取文件,指定为只读。
		RandomAccessFile raf=new RandomAccessFile("ran.txt","r");
		raf.skipBytes(8);//跳过八个字节
		byte[] buf=new byte[4];
		raf.read(buf);//先读到缓存中
		String name=new String(buf);
		int age=raf.readInt();	
		System.out.println("name="+name);
		System.out.println("age="+age);
		raf.close();
	}//将信息写入一个文件中,
	public static void writeFile()throws IOException{
		RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
		raf.write("李四".getBytes());
		raf.writeInt(97);
		raf.write("王五".getBytes());
		raf.writeInt(96);
		raf.close();
	}
}
字符编码:
编码:字符串变成字符数组。 
解码:字符数组变成字符串。
代码实现编码和解码的过程:

import java.util.*;
class  EncodeDemo{
	public static void main(String[] args)throws Exception {
		String s="你好";
		//用GBK编码
		byte[] b1=s.getBytes("GBK");
		System.out.println(Arrays.toString(b1));
		//这里演示使用ISO8859-1解码,出现乱码
		String s1=new String(b1,"ISO8859-1");
		System.out.println("s1="+s1);
		//再次进行ISO8859-1编码并输出编码结果
		byte[] b2=s1.getBytes("ISO8859-1");
		System.out.println(Arrays.toString(b2));
		//通过GBK解码
		String s2=new String(b2,"GBK");
		System.out.println("s2="+s2);
	}
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值