黑马程序员——IO流

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


这个章节是我目前为止学的最最吃力的了,太多东西需要记忆了。经过不停的翻阅API文档和毕老师总结一些东西,代码敲多了也就慢慢地能就记住一些方法了。IO的东西特别多,所以这篇博客也会很长的。接下来都是我在看毕老师的视频和自己敲代码的时候记录的笔记,总结了一下写出来。


IO:输入流和输出流相对于内存设备而言.

将外设中的数据读取到内存中:输入
将内存的数写入到外设中:输出。


字符流的由来:
其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。
在对这个文字进行操作。简单说:字节流+编码表

字节流的两个顶层父类:
1,InputStream  2,OutputStream.

字符流的两个顶层父类:
1,Reader 2,Writer

这些体系的子类都以父类名作为后缀。
而且子类名的前缀就是该对象的功能。


字符流的特点:


数据最常见的体现形式是:文件

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

用于操作操作文件的Writer的子类FileWriter,后缀名是父类名。前缀名是该流对象的功能。
操作步骤:
1.创建一个FileWriter对象。该对象一被初始化就必须明确要被操作的文件,该文件会被创建到指定目录下,如果该目录下已经有同名文件,将被覆盖
FileWriter fw=new FileWriter("demo.txt");
2.调用write方法,将字符串写入到流中。
fw.write();
3.刷新流对象中的缓冲中的数据,将数据刷到目的地
fw.flush();
4.关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中。和flush的区别,flush刷新后,流可以继续使用,close刷新后
将会将流关闭。
fw.close();

IO异常的处理方式:

FileWriter fw=null;
		
	try {
		fw=new FileWriter("demo.txt");
		fw.write("sdfasd");
		
	catch (IOException e) 
		{
			e.printStackTrace();
		}finally{
				
			try {
				if(fw!=null)
					fw.close();
				} catch (IOException e) {
					
					e.printStackTrace();
				}
				
			}
	}

文件的续写:
传递一个true参数,代表不覆盖已有文件,并在已知文件的末尾处进行数据续写。
FileWriter fw=new FileWriter("demo.txt",true);
换行转义字符:\r\n

文件的读取方式一:
FileReader();

1.创建一个FileReader对象。文件读取流对象,和指定名称的文件相关联,要保证该文件是已经存在的,如果不存在会发生异常
FileReader fr=new FileReader("demo.txt");
2.调用读取流的对象的read方法
    (1)int ch=fr.read();一次读一个字符,会自动往下读。
    (2)读出所有字符 
     while((ch=fr.read())!=-1)
    {
        System.out.println((char)ch);
     }


3.关闭流资源,
fr.close();

文件的读取方式2:通过字符数组进行读取
1.创建一个FileReader对象。文件读取流对象,和指定名称的文件相关联,要保证该文件是已经存在的,如果不存在会发生异常
FileReader fr=new FileReader("demo.txt");
2.定一个字符数组,用于存储读到字符,该rrad(char[])返回的是读到的字符个数。
char[] buf=new char[1024];一般定义1024-2个字节。
    int num=0;
     while((num=fr.read(buf))!=-1)
    {
        System.out.println((new String(buf,0,num));
     }

一个练习的例子:读取一个.java文件,并打印在控制台上。

FileReader fr=null;
		char[] buf=new char[1024];
		int num=0;
		try {
			fr= new FileReader("a.txt");
			
			try {
				while((num=fr.read(buf))!=-1){
					System.out.print(new String(buf,0,num));
				}
			} catch (IOException e) {
				
				e.printStackTrace();
			}
			
			
			
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		}
		finally
		{
				   try {
                               if(fr!=null)
					fr.close();
				} catch (IOException e) {
					
					e.printStackTrace();
				}		
		}

字符流的缓冲区:
缓冲区的出现提高了对数据的读写效率


对应类:
BUfferWriter
BufferedReader


特点:缓冲区要结合流才可以使用,在创建缓冲区之前,必须要有流对象。在流的基础上对流的功能进行了增强。

BUfferWriter步骤:
1.创建一个字符写入流对象
FileWriter fw=new FileWriter("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
bufferedWriter bufw=new BufferedWriter(fw);
buff.write("asdasdas");
bufw.newLine();//换行符,跨平台的
3.将缓冲区刷新
bufw.flush;
4.关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();

BufferedReader步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedReader bufr=new BufferedReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=bufr.readLine())!=null)
{
String s=line;}
4.关闭
bufr.close();

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

BufferTest:通过缓冲区复制一个文件

BufferWriter bufw=null;
	 BufferReader bufr=null;
	  try {
		  bufw=new BufferWriter(new FileWriter("b.txt"));
		  bufr=new BufferReader(new FileReader("a.txt"));
		 String line=null;
		  while ((line=buffr.read(buf))!=null){
			  bufw.write(line);
                    bufw.newLine();
                    bufw.flsuh;
		  }
	}
	  catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	  finally
		{
		   try {
				fr.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}		
			   
		   try {
				fw.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}		
		}

装饰设计模式:

当想要对已有的独享进行功能增强时,可以定义类,将已有的对象传入,基于已经有的功能,
并提供加强功能,那么自定义的该类称为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

代码事例:

//已知类:
Person()
{
  public void chifan()
   {
    }
}
//增强类:
superPerson()
{
   private Person p;
   superPerson(Person p)
   {
     this.p=p;
    }
   
    public void superchifan()
    {
      p.chifan();
      .........
    {
}

//自定义装饰类

package com.io;
import java.io.*;
public class MyBufferedReader  {
	
		private Reader r;
		


    	public MyBufferedReader(Reader r) {
			super();
			this.r = r;
		}

		//可以一次读取一行的方法
	 	public String myReadLine() throws IOException
	 	{
	 		//定义一个临时容器。StringBulider容器,应用于存储字符数组
	 		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;
	 	}
	 	
	 	//复写reader中的抽象方法
	 	//复写close方法
	 	public  void  close() throws IOException
	 	{
	 		r.close();
	 	}
	 	//复写read方法
	 	public int read (char[] c,int off,int len) throws IOException{
	 		
	 		return r.read(c, off, len);
	 	}
}

带有行号的缓冲区:
LineNumberReader lnr=new LineNumberReader();

获取行号:lnr.getLineNumber();
设置行号从几开始:lnr.setLineNumber(100);

LineNumberReader 步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
LineNumberReader lnfr=new LineNumberReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=lnfr.readLine())!=null)
{
String s=line;
String linenum=lnfr.getLineNumber();
}

4.关闭
lnfr.close();

自定义带行号的MyLineNumber;

public class MyLineBufferReader extends MyBufferedReader {


	public MyLineBufferReader(Reader r) {
		super(r);
		
	}
	
	private int LineNumber;


	public int getLineNumber() {
		return LineNumber;
	}


	public void setLineNumber(int lineNumber) {
		LineNumber = lineNumber;
	}
	
	public String myReadLine() throws IOException
	{
		LineNumber++;
		return super.myReadLine();
	}
}


字节流:
操作图片数据就要用到字节流。
字符流使用的是字符数组char[],字节流使用的是字节数组byte[]。

InputStream 读
Outputstream 写

//读取
FileInputStream fis=new FileInputStream ("a.txt");
byte[] buf=new byte[fis].available(0)];//定义一个刚刚好的缓冲区,不用再循环了
fis.read(buf);
System.out.println(new String(buf));
fis.close();


Test:复制图片

  FileOutputStream fw=null;
	  FileInputStream fr=null;
	  try {
		  fos=new FileOutputStream("b.jpg");
		  fis=new FileInputStream("a.jpg");
		  byte[] buf=new byte[1024];
		  int num=0;
		  while ((num=fis.read(buf))!=-1){
			 fis.write(buf,0,num);
		  }
	}
	  catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	  finally
		{
		   try {
                      if(fis!=null)
				fis.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}		
			   
		   try {
				fos.close();
			} catch (IOException e) {
				
				e.printStackTrace();
			}		
		}

日常的日志信息和系统信息

使用printStream();

输出到控制台:

System.SetOut(new PrintStream("sysinfo.txt"))
e.printStackTrace(System.out);

上面这两句就相当于
e.printStackTrace(new PrintStream("sysinfo.txt"));//将日志文件打印到文件中

获取系统信息:
 Properties prop =System.getProperties();
prop.list(System.out);//打印到控制台
prop.list(new PrintStream("sysinfo.txt"));//打印到文件中

字节流的缓冲区

通过字节流的缓冲区复制MP3

BufferedOutputStream
BufferedInputStream

源码:

BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("a.txt"));
		BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("b.txt"));
		
		int len=0;
		while((len=bufis.read())!=-1){
			bufos.write(len);
		}

//读取键盘录入

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

//代码 
InputStream in=System.in;
  int by=in.read();
   sop(by);
//结束录入 
  in.close();

转换流:

读取转换流:InputStreamReader
写入转换流:OutputStreamReader

读取转换流:InputStreamReader 字节流通向字符流的桥梁

步骤 
1.获取键盘录入对象
Inputstream in=System.in
2.将字节流对象转换成字符流对象,使用转换流InputStreamReader 
InputStreamReader isr=new InputStreamReader(in);
3.提高效率使用字符流缓冲区 BufferedReader进行读取
BufferedReader bf=new BufferedReader(is);
String line=null;
while((line=bf.readLine())!=null)
{
    if("over".equals(line))
     break;
    sop(line);
}
bufr.close;

写入转换流:OutputStreamReader 字符流通向字节流的桥梁

步骤 :

//1.获取输出对象
Outputstream out=System.out
//2.将字符流对象转换成字节流对象,使用转换流OutputstreamWriter 
OutputstreamWriter osw=new OutputstreamWriter(out);
//3.提高效率使用字符流缓冲区 BufferedWriter进行写入
BufferedWriter bw=new BufferedWriter(osw);
String line=null;
while((line=bf.readLine())!=null)
{
    if("over".equals(line))
     break;
    bw.write(line);
    bufw.newLine();
}
bufr.close;


流操作基本规律:
两个明确:
1.明确源和目的

   源:输入流。InputStream字节流  Reader 字符流
   目的:输出流 OutPutStream 字节流  Writer 字符流
 2.操作的数据是否是纯文本

   是 就是字符流 如果设备是键盘 就将字节流转换为字符流
   不是 就是 字节流

3.当体系明确后,在明确要是用那个具体的对象
    通过设备来区分 
     源设备  内存 硬盘 键盘
     目的设备  内存  硬盘  控制台

4.是否需要提高效率  是 BufferedReader  BufferedInputStream
                   否 BuffreredWriter BufferedOutputStream
 
案例分析 :

1.将一个文本文件中的数据存储到另一个文件中,复制文件
 
  源: InputStream字节流  Reader 字符流
  是否是纯文本 是  Reader
   设备: 文件   操作文件的对象 就是FileReader
  是否需要高效 
  是  BufferedReader
   FileReader fr=new FileReader("a.txt");
   BufferedReader bufr=new BufferedReader(fr);
  
 目的   OutPutStream 字节流  Writer 字符流
 是否是纯文本 :是 Writer 
 设备: 文件 写入文件的对象 就是 FileWriter 
 是否需要高效  是   BufferedWriter


  FileWriter fw=new FileWriter("b.txt");
   BufferedWriter bufw=new BufferedWriter(fw);


2.将一个图片文件数据存储到另一个文件中,复制文件。

分析
源:
 是否是纯文本 : 不是  InputStream
 设备 文件 就是 FileInputStream
  是否高效 ?是
 BufferedInputStream
  
   FileInputStream isr=new FileInputStream("a.jpg");
    BufferedInputStream bufis=new BufferedInputStream(isr);
目的:
  是否纯文本 :不是 OutPutStream
  设备:文件 FileOutPutStream
是否高效? 是
 BufferedOutputStream
 FileOutPutStream osw=new FileOutPutStream("b.jpg");
    BufferedOutputStream bufos=new BufferedOutputStream(osw);

3.需求将键盘录入的数据保存到一个文件中 。

 源:键盘  字节流 
  是否纯文本  Reader
  设备 :键盘  ,对应的对象时 System.in 对应的是字节流 ,为了操作方便 转成字符流
  既然明确了Reader 就将System.in 转换成字符流 InputStreamReader
  
  InputStreamReader isr=new InputStreamReader(System.in);

  需要高效吗 ?
 
  BufferedReader bufr=new BufferedReader(isr);

  目的: 文件
   是否纯文本 是  Writer
   设备:文件 FileWriter
   需要高效吗?
   是 BufferedWriter
 
4.扩展 :想要吧录入的数据按照指定的编码表(utf-8)将数据存到文件中
   目的:OutPutStream 字节流  Writer 字符流
   是否是存文本:是  Writer
   设备 :文件 fileWriter
   默认编码表是 gbk
   编码标只有转换流可以指定。所以要使用的对象是写入转换流 OutputStreamWriter
   转换流需要接受一个自己输出流,操作字节输出流的是FileOutputStream
   OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("b.txt"),"utf-8");
  BufferedWriter bufw=new BufferedWriter (osw);

通常涉及到字符编码转换的时候,就需要用到转换流。

File类:

创建File对象,
1.File f=new File("c:\\abc\a.txt");//将a.txt封装成FIle对象,可以将已有的和未出现的文件或者文件夹封装成对象。
2.File f=new File("c:\\abc","a.txt"); 第一个参数代表的是目录,第二个参数代表的是目录下的文件。
3.file d=new File("c\\abc"); 将路径封装成对象
  File f=new File(d,"a.txt"); 调用路径对象

f代表的是文件路径

目录分隔符:\\
File.separator 

常见方法:
1.创建
  boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false
                          和写入流不一样,写入流创建文件会覆盖已经存在的文件。
  案例 :
   File f=new File("a.txt");
   f.createNewFile();
   创建一级目录 
   File dir=new File("abc");
   dir.mkdir();
   创建多级目录
   dir.mkdirs();

2.删除
   boolean f.delete(); 删除失败,返回false,可能不能删除
   void deleteOnExit();在程序退出时,删除指定文件。必须删除。不会失败

3.判断 :在判断文件对象是都是文件或者目的时候,必须要先判断该文件对象封装的内容是否存在。
   File f=new File("a.txt");
   f.canExecute();是否能执行。
   f.exits();返回boolean  文件是否存在
   是否是目录 
   f.isDirectory();
   是否是文件
   f.isFile();
   是否是隐藏的
   f.isHidden();
   是否是绝对路径
   f.isAbsolute();

4.获取信息。
   getName()   //获取名称
   getpath()    //获取路径
   getAbsolutePath() //获取绝对路径 
   getParent() //获取绝对路径下的父路径,如果获取的是相对路径返回null,如果相对路径中由上一级目录,该目录就是结果。
   lastModified()//获取最后一次修改时间
   length();//获取体积大小
5.其他
   renameTo();改名,重命名,如果修改路径的话,同时路径也会修改
   f1.renameTo(f2);
   
    listRoots();返回 File 数组,列出可用的文件系统根(盘符) 
   例子:
    

File[] files=File.listRoots();
     for(File f: files)
     {
               sop(f)
     }

     list():返回当前目录下所有文件,包括子目录
     File f=new File("abc");
     String[] namess=f.list();//调用list方法的file对象必须封装了一个目录,把那个目录必须存在
     for(String f: names)
     {
               sop(f)
     }

    显示.bmp结尾的文件
      list(FilenameFilter Filter) 返回String[]  指定目录中满足制定过滤器的文件和目录
       File dir=new File("abc");

     String[] namess=f.list(new FilenameFileter()


           public boolean accept(File dir,String name)
               {
                  return name.endsWith(".bmp");
                  }
     );
     for(String f: names)
     {
               sop(f);
     }
     
     listFiles();返回当前路径下的文件对象。(不包括子目录)
      
     FIle dir=new File("c:\\"); 
     File[] files=dir.listFiles();
     for(File f : files)
      {
          sop (f.getname())
      }        


列出指定目录下所有内容:使用递归 。。函数自己调用自己

 File dir=new File("d:\\");
     sop(dir);
     File[]  files=dir.listFiles();
     for(int x=0;x
       
删除一个带内容的目录:

原理:从里面往外删除,就需要递归
 
File dir=new File("d:\\");
File[] files=dr.listFiles();
for(int x=0;x


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

详细请查看http://www.itheima.com/




你可能感兴趣的:(Java基础,android,java,面向对象,黑马程序员)