黑马程序员 IO流(1)

-------android培训、java培训、期待与您交流! ----------

IO(Input Output)

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

Java对数据的操作就是通过流的方式

Java用于操作流的对象都在IO包中

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

流按流向分为:输入流,输出流

IO流常用基类:

字节流的抽象基类:

InputStreamOutputStream

字符流的抽象基类:

ReaderWriter

注:由这四个类派生出来的子类名称都是以其父类名

作为子类名的后缀。

如:InputStream的子类FileInputStream

如:Reader的子类FileReader

第一节 字符流

一.概述。

1.字符流中的对象融合了编码表。使用的时默认的编码,即当前系统的编码。

2.字符流只用于处理文字数据,而字节流可以处理媒体数据。

既然IO流失用于操作数据的,那么数据的最常见体现形式是:文件

 

那么先以操作文件为主来演示

需求:在硬盘上,创建一个文件并写入一些文字数据。

 

找到一个专门用于操作文件的Writer子类对象。FileWriter。后缀名

是父类名。前缀名是该流对象的功能。

 

Import  java.io;
class FileWriterDemo
{
   public static void main(String[] args) throws IOEception
  {
  //创建一个FileWriiter对象。该对象一被初始化就必须要明确被操作的文件。
  //如果没有该文件,就会被创建在指定的目录下。如果该目录下已有同名文件,将被覆盖
  //其实该步就是在明确数据要存放的目的地

     	 FileWriter  f = new FileWriter(“demo.txt”);
   //调用write方法,将字符串写入到流中。
   f.writer();
   //刷新流对象中的缓冲中的数据。
  //将数据刷到目的地中。
   f.flush();
  //关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
  //将数据刷到目的地中。
  //close和flush区别,flush刷新后,流可以继续使用,close刷新后,会将流关闭
  f.close();
  
  }
}

IO异常的处理方式。

示例代码:

Import   java.io.*;
class FileWriterDemo2
{
   public static void main(String[] args){
    FileWriter fw = null;
    try{
   fw = new FileWriter(“demo.txt”);
  fw.write(“abcdefg”);
  fw.close();
  }
  catch(IOException e){
      System.out.println(e.toString());
  } 
  finally{
      try{
           if(fw!=null){
  fw.close();
             }
        }
      catch(IOException e){
            System.out.println(e.toString());
        }
  }
}
}

文件的续写是通过FileWriter的构造函数FileWriter(String pathname,boolean append)指定boolean值来确定是否能续写。如true代表可以续写,数据是写在文件末尾处,而不是文件开头处。

 2.读取字符流:

文件文本的读取方式一:

//创建一个文件读取流对象,和指定名称的文件相关联。

//要保证该文件是否已经存在,如果不存在,就会发生FileNotFoundException异常

FileReader fr =  new FileReader(“demo.txt”);

//调用读取流对象的read方法。

//read():一次读一个字符。而且会自动往下读。

文件文本的读取方式二: int read(char[] char) ;  返回的是读取的字符数。如已达到文件末尾返回-1

通过字符数组进行读取。


文本文件读取练习:

//读取一个.java文件,并打印在控制台上。

实例:

package itcast;
import java.io.*;
public class FileReaderDemo {
	public static void main(String[] args) throws IOException{
		  //创建字符读取流
		  FileReader fr = new FileReader("E:\\webserver\\itcast\\src\\itcast\\IoText.java");
		  char[]  ch = new char[1024];
		  int len=0;
		  while((len=fr.read(ch))!=-1){
			   System.out.print(new String(ch,0,len));
		  }
	}

}

c盘一个文本文件复制到D

 

复制的原理:

其实就是将c盘下的文件数据存储到d盘的一个文件中。 

步骤:

1.在D盘创建一个文件。用于存储c盘文件中的数据。

2.定义读取流和c盘文件关联。

3.通过不断地读写完成数据存储。

4.关闭资源。

示例代码:

package itcast;
/*
 * 
 */
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyDemo {
	    public static void main(String[] args){
             copy_2();
	    }
	    //方式二:先将数据缓存进char数组,再一次性写入到f盘中
	    public static void copy_2(){
	    	FileWriter fw =null;
	    	FileReader fr = null;
	    	  try {
				fw= new FileWriter("f:\\yangfen.txt");
				fr = new FileReader("e:\\java.txt");
				char[] buf = new char[1024];
				int len =0;
				while((len=fr.read(buf))!=-1){
					fw.write(buf, 0, len);
					
				}
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			finally{
				 if(fw!=null){
					  try {
						fw.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				 }
				 if(fr!=null){
					  try {
						fr.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				 }
			}
	    }
	    //方式一:读取e盘下的java.txt文件,在一个个写入到f盘中
        public static void copy_1(){
        	 FileWriter fw =null;
        	 FileReader fr = null;
        	 try{
        		  fw  = new FileWriter("f:\\yangfen.txt");
        		  fr = new FileReader("e:\\java.txt");
        		  int len=0;
        		  while((len=fr.read())!=-1){
        			   fw.write(len);
        		  }
        	 }
        	 catch(Exception e){
        		 e.printStackTrace();
        	 }
        	 finally{
        		 if(fw!=null){
					  try {
						fw.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				 }
				 if(fr!=null){
					  try {
						fr.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				 }
        	 }
        }
}

字符流的缓冲区:

1.缓冲区的出现是为了提高流的操作效率而出现的。

所以在创建缓冲区之前,必须要先有流对象。

2.缓冲的原理:对象里面封装了数组,先把数据存进数组,再一次性缓冲出来。

3.为了提高字符写入流效率。加入了缓冲技术。只需要将被提高效率的流对象作为参数传递给缓冲区的构造函数即可。

4.记住,只要用到缓冲区,就要记得刷新。

5.其实关闭缓冲区,就是在关闭缓冲区中的流对象。

 

缓冲字符输出流

BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组,和字符串的高效写入。

BufferedWriter提供了一个跨平台的换行方法。 newLine();

缓冲字符输入流:

BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取。

在对象创建时,也需要被缓冲的流对象即(Reader in 

如何实现缓冲字符输入流的使用:

1.创建一个读取流对象和文件相关联。

2.为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。

3.该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。当达到文件末尾时,返回null

注意:readLine()方法不包含任何行终止符。

readLine()方法原理:无论是读一行,获取读取多个字符。其实最终都在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个方法。

 

缓冲区要结合流才可以使用。

在流的基础上对流的功能进行了增强

通过缓冲区复制一个.java文件。

示例代码:

package itcast;

import java.io.*;
public class CopyTextByBuf {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		  //创建缓冲字符输入流
          BufferedReader bufr = null;
          //创建缓冲字符输出流
          BufferedWriter bufw = null;
          try{
        	   bufr = new BufferedReader(new FileReader("e:\\java.txt"));
        	   bufw = new BufferedWriter(new FileWriter("f:\\java_copy.txt"));
        	   String line=null;
        	   while((line=bufr.readLine())!=null){
        		   bufw.write(line);
        		   bufw.newLine();
        		   bufw.flush();
        	   }
          }
          catch(Exception e){
        	  e.printStackTrace();
          }
          finally{
        	   if(bufr!=null){
        		   try {
					bufr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
        	   }
        	   
         	   if(bufw!=null){
        		   try {
					bufw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
        	   }
        	   
          }
	}

}

自定义MyBufferedReader类模仿BufferedReader的方法readLine();

 示例:

package itcast;
import java.io.*;
//自定一个MybufferedReader类模仿BufferedReader类的read'Line()方法
public class MybufferedReader {
	private Reader in;
	//创建构造函数在对象创建时就传入读取流对象
	public MybufferedReader(Reader in){
		this.in=in;
	}
	public String myRead() throws IOException{
		//创建存储字符串的容器
		StringBuilder sb = new StringBuilder();
		int line=0;
		while((line=in.read())!=-1){
			if(line=='\r')
			   continue;
			if(line=='\n'){
				return sb.toString();
			}
			else{
			sb.append((char)line);  //往容器中添加数据
			}
		
		}
		if(sb.length()!=0){
			return sb.toString();
		}
		return null;
	}
	public void myClose() throws IOException{
		 in.close();
	}

	public static void main(String[] args) throws IOException {
		  MybufferedReader  br = new MybufferedReader(new FileReader("e:\\java.txt"));
		  String line=null;
		  while((line=br.myRead())!=null){
			  System.out.println(line);
		  }
		  br.myClose();
	}
}


装饰设计模式:

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的对象,并提供加强功能。

那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接收被装饰的对象。

并基于被装饰的对象的功能,提供更强的功能。

装饰模式比继承要灵活,避免了继承体系臃肿。

而且降低了类与类之间的关系。

特点:

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。

所以装饰类和被装饰类通常都属于一个体系中的。

 

LineNumberReader跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

自定义一个类模拟LineNumberReader获取行号方法

示例代码:

package itcast;
import java.io.*;
public class MyLineNumberReader {
	  private Reader r;
	  public MyLineNumberReader(Reader r){
		  this.r=r;
	  }
	  private int linenumber;
	  public int getLineNumber(){
		 return linenumber;    
	  }
	  public void setLineNumber(int linenumber){
		  this.linenumber=linenumber;
	  }
	  public String myReadLine() throws IOException{
		   linenumber++;
		   StringBuilder sb = new StringBuilder();
		   int line=0;
		   while((line=r.read())!=-1){
			    if(line=='\r')
			    	continue;
			    if(line=='\n'){
			    	 return sb.toString();
			    }
			    else{
			    	sb.append((char)line);
			    }
			    
		   }
		   if(sb.length()!=0){
			   return sb.toString();
		   }
		   return null;
	  }
	  
	  public static void main(String[] args) throws IOException{
		    FileReader fr = new FileReader("e:\\java.txt");
		    MyLineNumberReader mnr = new MyLineNumberReader(fr);
		    String line=null;
		    while((line=mnr.myReadLine())!=null){
		    	 System.out.println(mnr.getLineNumber()+"---"+line);
		    }
	  }

}

第二节 字节流

一.概述:

基类:OutputStream 输出流(写)  和InputStream  输入流(读)

1.字节流和字符流具体操作数据的方法是相似的,只不过是字符流操作的字符数据,字节流操作除了可以操作字符数据还可以操作媒体数据,

2.使用字节流写入数据不需要对流进行刷新,就能把数据写入到文件中。因为数据存储在电脑中都是用字节存储的。

3. 特有方法:int available() --->  回数据字节的长度,包含终止符

  这个方法的作用就是可以省去写入数据时的while条件,能准确的判断将要写的文件的所包含的字节数。但是这个方法要慎用,因为如果你要把一个大数据文件(比如电影),你new一个这个大的字节数组。内存是会溢出的。因为jvm的默认大小是为(64M)

需求:复制一个图片

思路:

1.用字节流读取流对象和图片相关联。

2.用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。

3.通过循环读写,完成数据的存储。

4.关闭资源。

package itcast;

import java.io.*;

public class Copy {
	public void copy_1(){
		BufferedInputStream bfs=null;
		BufferedOutputStream bos =null;
		try {
			bfs = new BufferedInputStream(new FileInputStream("e:\\1.mp3"));
			bos= new BufferedOutputStream(new FileOutputStream("e:\\2.mp3"));
			int len=0;
			while((len=bfs.read())!=-1){
				bos.write(len);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally{
			if(bfs!=null){
				try {
					bfs.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(bos!=null){
				try {
					bos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	public static void main(String[] args){
		 Copy c = new Copy();
		 long start = System.currentTimeMillis();
		 c.copy_1();
		 long end = System.currentTimeMillis();
		 System.out.println((end-start)+"毫秒");
		 
	}

}

自定义字节流缓冲区:

思路:
1、定义一个固定长度的数组
2、定义一个指针和计数器用于读取数组长度,和计数数组元素是否取完为0
3、每次将字节数据存入元素要先将数组中的元素取完

示例代码:

package itcast;

import java.io.IOException;
import java.io.InputStream;

public class InputStremDemo {
	 private InputStream is;
	 public InputStremDemo(InputStream ism){
		 this.is=ism;
	 }
	 private byte[]  buf = new byte[1024];
	 private int count,pos=0;
	 public int 	myRead(){
		 if(count==0){
			  try {
				count = is.read(buf);
				
				
				if(count<0){
					return -1;
				}
				pos=0;
				 byte b =buf[pos];
				 count--;
				 pos++;
				 return b&255;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		 }
		 else if(count>0){
			 byte b = buf[pos];
			 count--;
			 pos++;
			 return b&0xff;
		 }
		 return -1;
		 
	 }
	 
	 public void myClose(){
		  try {
			is.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	 }

}

第三节 读取键盘录入

一.读取键盘录入:

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

2.System.in:对应的标准的输入设备,键盘

二.转换流:

InputStreamReader:读取转换流。

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

OutputStreamWriter:写入转换流。

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

示例代码:

package itcast;

import java.io.*;

public class TransStreamDemo {
	public static void main(String[] args){
		  InputStream in = System.in;
		  InputStreamReader isr = new InputStreamReader(in);
		  BufferedReader  br = new BufferedReader(isr);
		  
		  OutputStream os = System.out;
		  OutputStreamWriter  osw = new OutputStreamWriter(os);
		  BufferedWriter  bw = new BufferedWriter(osw);
		  
		  String line=null;
		  try {
			while((line=br.readLine())!=null){
				  if("over".equals(line)){
					  break;
				  }
			     bw.write(line.toUpperCase());
			     bw.newLine();
			     bw.flush();
				  
			  }
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			osw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

第四节  异常的日志信息

一、异常的日志信息:

当程序在执行的时候,出现的问题是不希望直接打印给用户看的,是需要作为文件存储起来,方便程序员查看,并及时调整的。

package itcast;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionInfo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
           try{
			int[]  num = new int[2];
           System.out.println(num[3]);
           }
           catch(Exception e){
        	   PrintStream ps =null;
        	    try {
        	    	ps=  new PrintStream("exception.log");
        	    	Date d = new Date();
        	    	SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        	    	String s =sf.format(d);
        	    	ps.println(s);
					
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					throw new RuntimeException("日志文件创建失败");
				}
				System.setOut(ps);
        	     e.printStackTrace(System.out);
           }
	}

}

二.系统信息。

示例将系统信息打印到文件中。

package itcast;

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Properties;

public class Systeminfo {
	public static void main(String[] args){
		 Properties p =System.getProperties();
		 try {
			p.list(new PrintStream("systeminfo.log"));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值