【黑马程序员】java中---------------IO流

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------





一、IO流

1、IO流是用来处理设备之间的数据传输

2、java对数据的操作是通过流的方式

3、java用于操作流的对象都在IO包中

4、流按操作数据分为两种:字节流与字符流

5、流按流向分为:输出流与输入流


A、字符流体系

基类:Reader-----InputStreamReader字节转字符的读取流-------FileReader字符读取流

|----BufferedReader字符缓冲区---------LineNumberReader基于缓冲区的行号读取流

|-----CharArrayReader字符输入流的字符缓冲区

|-----FilterReader用于读取已过滤的字符流的抽象类--------PashbackReader

|-----PipedReader字符管道读取流

|-----StringReader字符串读取流

基类:Writer

|----FileWriter字符文件输出流

	|--BufferedWriter字符缓冲输出
	|----OutStreamWriter字符转换输出
	|----PipedWriter 字符管道输出
	|----PrintWriter 字符文本打印输出
	|----StringWriter字符串输出
	|----CharArrayWriter字符数组输出

B、字节流体系

基类:InputStream

|----FileInputStream字节文件读取流

|----ObjectInputStream反序列化读取流

|----FilterInputStream过滤流

|----BufferedInputStream字节缓冲读取流

|----DataInputStream基本数据字节读取流

|----PipedInputStream字节管道读取流

|----SequenceInputStream合并字节流。没有与之相对应的输出流

|----ByteArrayInputStream字节数组读取流

基类:OutputStream

|----FileOutputStream字节文件输出

|----ObjectOutputStream序列化输出

|----FilterOutputStream过滤流

|----BufferedOutputStream字节缓冲输出

|----DataOutputStream基本数据字节输出

|----PrintStream字节打印流

|----PipedOutputStream字节管道输出

|----ByteArrayOutputStream字节数组输出


二、缓冲技术
1、字节流当中:BufferedInputStream读取流缓冲技术,它的内部封装了byte[]字节数组
		  BufferedOutputStream输出流缓冲技术,要注意的是:flush()刷新
2、字符流中:

BufferedReader读取流缓冲技术,内部封装了数组

特有方法:readLine()方法,一次读一行


BufferWriter输出流缓冲技术,

特有方法:newLine()换行方法

flush()刷新方法

三、转换流

1、字节向字符流的转换:InputStreamReader类:InputStreamReader(InputStream in)

其次还可以指定字符编码的功能:InputStreamReader(InputStream in,String charsetName) 创建使用指定字符集的 InputStreamReader。

2、字符转换成字节流:OuputStreamWriter类:OutputStreamWriter(OutputStream out)

其次还可以指定字符编码的功能:OutputStreamWriter(OutputStream out,String charsetName)  创建使用指定字符集的 OutputStreamWriter。

四、输出流对象的续写功能
1、FileOutputStream类中,构造函数 FileOutputStream(String name, boolean append)
       第一个参数:接收字符串文件名
第二个参数:接收一个布尔型值,为真,就在文件末尾处继续写入数据,
2、FileWriter类中,构造函数 FileWriter(String fileName, boolean append)
第一个参数:接收字符串文件名
第二个参数:接收一个布尔型值,为真,就在文件末尾处继续写入数据,

五、只有BufferedReader类中,readLine()一次读一行的方法
子类LineNumberReader类中,getLineNumber()获取行号方法和setLineNumber()设置行号方法

a、为了了解他的原理:来自定义MyBufferedReader类,模拟readLine()方法
/*装饰设计模式:装饰的类和被装饰的类通常同属一个体系中,同属一个父类或者接口
定义:当想对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,
	  并提供加强功能,那么自定义类称为装饰类

模拟ReadLine()方法,一次读一行
abstract  int read(char[] cbuf, int off, int len) 
          将字符读入数组的某一部分。 
abstract  void close() 
          关闭该流并释放与之关联的所有资源。 

*/
import java.io.*;
//用到装饰设计模式,继承Reader基类
class  myBufferedReader extends Reader{
	private Reader r;
	myBufferedReader(Reader r){
		this.r=r;
	}
	//自定义一个myReaderLine()方法
	public String myReadLine()throws IOException
	{
		//定义一临时容器.StringBuilder
		StringBuilder sb=new StringBuilder();
		int ch=0;
		//调用父类的read()方法
		while((ch=r.read())!=-1){
			if(ch=='\r')
				continue;
			if(ch=='\n')
				return sb.toString();
			else
				sb.append((char)ch);
		}
		if(sb.length()!=0)//如果已读数据没有\r\n需要判断,
			return sb.toString();
		return null;
	}
	public void myClose()throws IOException
	{
		r.close();
	}
	//复写父类的两个抽象方法
	public int read(char[] cbuf, int off, int len)throws IOException
	{
		return r.read(cbuf, off,len);
	}
	public void close()throws IOException
	{
		r.close();
	}
	
}
class myReaderLineDemo_1{
	public static void main(String[] args)throws IOException
	{
		FileReader fr=new FileReader("buff.txt");
		myBufferedReader myBuf=new myBufferedReader(fr);
		String line=null;
		while((line=myBuf.myReadLine())!=null){
			System.out.println(line);
		}
		myBuf.myClose();
	}	
}

b、自己定义一个MyLineNumberReader类,模拟getLineNumber(),setLineNumber()方法
/*装饰设计模式:MyLineNumber继承myBufferedReader类
增强功能,myLineNumber()方法

Reader类----
	|---BufferedReader类
			|------LineNumberReader类   方法:getlineNumber();  setLineNumber()
	|------自定义增强类;myBufferReader类   方法:myReadLine();
								|-------------自定义增强类:MyLineNumberReader类  
								复写方法:myReadLine();
								特有:setLineNumber();
								特有:getLineNumber();
								*/


import java.io.*;
class MyLineNumberReader extends myBufferedReader{
	
	private int lineNumber;
	//构造函数传父类,多态
	MyLineNumberReader(Reader r){
		//引用父类的构造函数
		super(r);
	}
	public String myReadLine()throws IOException
	{
		lineNumber++;
		//引用父类的myReaderLine()方法
		return super.myReadLine();
	}
	public int getLineNumber(){
		return lineNumber;
	}
	public void setLineNumber(int lineNumber){
		this.lineNumber=lineNumber;
	}
}
class MyLineNumberReaderDemo_2{
	public static void main(String[] args)throws IOException
	{
		FileReader fr=new FileReader("FileWriterDemo2.java");
		
		MyLineNumberReader mlnr=new MyLineNumberReader(fr);
		String line=null;
		while((line=mlnr.myReadLine())!=null){
			System.out.println(mlnr.getLineNumber()+":"+line);
		}
		mlnr.myClose();
	}
}

六、装饰设计模式
1、定义:当想对已经有的对象进行功能增强时,就可以定义一个类,将已有的对象传入
基于已有的功能,并提供加强的功能,那么这个自定义的类称为装饰类
通常装饰类会通过构造函数接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能

2、其实,LineNumberReaders类和BufferedReader类 都是装饰类,
装饰类与被装饰的类通常属于一个体系中,同属于一个父类或者接口

3、   比方说我们现在有一个专门读取数据的类MyReader它的继承体系如下:

MyReader

|--MyTextReader 用于操作文本文件的类

       |--MyBufferTextReader用来缓冲操作文本文件的类

|--MyMediaReader 用于操作媒体文件的类

       |--MyBufferMediaReader用来缓冲操作媒体文件的类

|--MyDataReader 用于操作数据的类

       |--MyBufferDataReader用来缓冲操作数据文件的类

如果运用装饰设计模式:这个继承体系更简单,

MyReader

|--MyTextReader 用于操作文本文件的类

|--MyMediaReader 用于操作媒体文件的类

|--MyDataReader 用于操作数据的类

|--MyBufferReader用来缓冲操作数据文件的类,只剩下这一个类了。


七、读取键盘录入
1、
/*读取键盘录入:
	父类:OutputStream 
				|--FilterOutputStream
						|-->PrintStream<----返回    Sysrem.out:对应的的标准的输出设备,控制台
	InputStream <--返回    System.in:对应的是标准的输入设备:键盘

需求:通过键盘录入数据
1,当录入以后数据后,就将该数据进行打印
2,如果录入的数据是over,那么就停止录入*/

import java.io.*;
class ReadIn{
	public static void main(String[] args)throws IOException
	{
		InputStream in=System.in;
		
		//readIn(in);
		
		readIn( in);
		
	}	
	/*第一种读取键盘录入的方式
	思路:1.接收一个键盘录入返回的InputStream字节流对象,
		  2.建立一个StringBuileder容器(相当于缓冲区),调用字节流中read()方法,
		  将每次读取一个字节,存放进容器中
		  3,。再将容器中的数据转化成大写打印,每次打印完需要清空容器
		  */
	public static void readIn(InputStream in)throws IOException
	{
		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);
			
				
		}
	}
		/*第二种方式:转换流的应用:
		思路:1.将键盘录入返回的字节流InputStream对象
			  2.通过转换流:InputStreamReader类,将其转换成字符流,
			  3.再通过建立BufferedReader类对象,字符缓冲技术,接收字符流
			  4.使用:缓冲区中readLine()方法,一次读一行的方法
		*/
		public static void ReadLineDemo(InputStream in)throws IOException
		{	
			//将字节流转换成字符流,InputStreamReader类,
			InputStreamReader isr=new InputStreamReader(in);
			//为了提高效率,将字符流 进行缓冲区技术高效操作,用缓冲区BufferedReader类
			BufferedReader bufr=new BufferedReader(isr);
			String line=null;
			while((line=bufr.readLine())!=null){
				if("over".equals(line))
					break;
				String s=line.toUpperCase();
				System.out.println(s);
			}
			bufr.close();
		}
	
	
}
标准的键盘录入和标准的输出设备:
/*字节流转换字符流
在InputStream中,键盘录入的方法是read()
而在Reader类中 1,BufferedReader子类中才有readLIine()方法

2,子类InputStreamReader是字节流通向字符流的桥梁,*/



import java.io.*;
class zhuanHuanLiu{
	public static void main(String[] args)throws IOException
	{	//获取键盘录入
		
		InputStream in=System.in;
		
		//将字节流对象转换成字符流对象,InputStreamReader类
		InputStreamReader isr=new InputStreamReader(in);
		
		//为了提高效率,将字符流 进行缓冲技术操作。使用BufferedReader
		BufferedReader bufr=new BufferedReader(isr);
		
		/*String line=null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))//自定义结束标记
				break;
			System.out.println(line);
			System.out.println(line.toUpperCase());
		}
		*/
		
		//获取输出设备
		OutputStream out=System.out;
		
		//字符流通向字节流对象:OutputStreamWriter类
		OutputStreamWriter osw=new OutputStreamWriter(out);
		
		//提高效率,将字符流进行缓冲区高效操作,BufferedWeriter
		BufferedWriter bufw=new BufferedWriter(osw);
		
		String line=null;
		while((line=bufr.readLine())!=null)
		{	
			if("over".equals(line))
				break;
			bufw.write(line);
			bufw.newLine();
			bufw.write(line.toUpperCase());
			bufw.newLine();//BufferedWriter类中的换行方法
			bufw.flush();//刷新
		}
		bufr.close();
	}
}

改变读取源和改变输出目的的两个方法:
/*
	改变源和目的的两个方法:
	static void setIn(InputStream in) 
          重新分配“标准”输入流。 
	static void setOut(PrintStream out) 
          重新分配“标准”输出流。 
		  PrintStream(String fileName) 
          创建具有指定文件名称且不带自动行刷新的新打印流。
*/

import java.io.*;
class SystemIn{
	public static void main(String[] args )throws Exception
	{	
		//设置源
		System.setIn(new FileInputStream("流规律.txt"));
		//设置目的
		System.setOut(new PrintStream("流规律_1.txt"));
	
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		
		BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
		String line=null;
		while((line=br.readLine())!=null){
			if("over".equals(line))
				break;
			//bw.write(line.toUpperCase());
			bw.write(line);	
			bw.newLine();	
			bw.flush();
		
			
			
		}
		br.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返回的是输出流对象,初始化须有文件,文件须抛异常
				PrintStream ps=new PrintStream("日志信息.txt");
				
				ps.println(s);//相当于ps.write(s.getBytes());
				System.setOut(ps);
			}
			catch(Exception ex)
			{
				throw new RuntimeException("日志信息建立失败");//捕获异常并处理
			
			
			}
		
			e.printStackTrace(System.out);//捕获并,处理角标越界异常
		}
	}
}
HashMap集合 的子类Properties集合与IO相结合的技术用于配置文件的创建和读取
1、集合中load()方法,从输入流中读取键值对信息
2、Set ---stringProopertyNames(),获取Properties集合中的所有键的set集合
3、Properties集合中的:list(PrintStream   out)方法
store(outputStream   out,   String      comments)

/*	properties 是HashMap的子类
1.也就是说他具备map集合的特点,而且它里面存储的键值对都是字符串

2.是集合中和IO技术相结合的集合容器
	该对象的特点:可以用于键值对形式的配置文件
 String getProperty(String key) 
          用指定的键在此属性列表中搜索属性。 
 String getProperty(String key, String defaultValue) 
          用指定的键在属性列表中搜索属性。 
 Object setProperty(String key, String value) 
  
  Set<String> stringPropertyNames() 获取map集合中,键的set集合
  void load(InputStream inStream) 
          从输入流中读取属性列表(键和元素对)。 
 void load(Reader reader) 
          按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 

 void list(PrintWriter out) 
          将属性列表输出到指定的输出流。 
void store(OutputStream out, String comments) 
 		  
*/

import java. io.*;
import java.util.*;
class PropertiesDemo{
	public static void main(String[]  args)throws IOException
	{
		
		//getKey();
		
		//mothed_1();
		mothed_2();
	}
	public static void mothed_2()throws IOException
	{
		FileInputStream fis=new FileInputStream("配置文件.txt");
	
		Properties pro=new Properties();
		pro.load(fis);
		//System.out.println(pro);
	
		pro.setProperty("shengao","185");//发现只能修改内存的数据,文本中没变
		//pro.list(System.out);
		
		//通过此方法解决,将修改的数据写到文本中
		FileOutputStream fos=new FileOutputStream("配置文件_1.txt");
		pro.store(fos,"store()方法");
		pro.list(System.out);
		
		fos.close();
		fis.close();
	}
	//通过文本缓冲区读取,中的readLine(),在遍历的时候,进行字符串切割,返回字符串数组
	//再通过往Properties集合设置键值对
	
	public static void mothed_1()throws IOException
	{
		BufferedReader bufr=new BufferedReader(new FileReader("配置文件.txt"));
		Properties pro=new Properties();
		
		String line=null;
		while((line=bufr.readLine())!=null){
			String[] s=line.split("=");
			pro.setProperty(s[0],s[1]);
		}
		bufr.close();
		System.out.println(pro);
	
	}
	public static void getKey(){
		Properties pro=new Properties();
		pro.setProperty("zhangs","18");
		pro.setProperty("lisi","38");
		pro.setProperty("wangwu","28");
		
		System.out.println(pro);
		String s=pro.getProperty("lisi");
		System.out.println(s);
		
		Set<String> name=pro.stringPropertyNames();
		
		for(String names:name){
		
			System.out.println( names+"---"+pro.getProperty(names));
		}
	}
}


联习代码:控制程序的运行次数
/*
	练习:用配置文件记录住程序的运行次数,使用次数已到,那么就给出提示
	键值对:map集合+ IO技术--------->用到Properties类
*/

import java.io.*;
import java.util.*;
class PropertiesDemo2{
	public static void main(String[] args)throws IOException
	{
		store();
	}
	public static void store()throws IOException
	{
		File file=new File("配置文件_2.ini");
		if(!file.exists())
			file.createNewFile();
		FileInputStream fis=new FileInputStream(file);
		Properties pro=new Properties();
		pro.load(fis);
		int count=0;
		String value=pro.getProperty("time");
		
		if(value!=null)
		{
			 count=Integer.parseInt(value);
			
			if(count>=5)
			{
				System.out.println("使用次数已到,请交钱");
				return ;
			}
		}
		
		count++;
		pro.setProperty("time",count+"");
		
		FileOutputStream fos=new FileOutputStream(file);
		pro.store(fos,"peizi");
		
		fis.close();
		fos.close();
	}
	
}





---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------











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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值