黑马程序员_IO输入与输出(1)

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

1、IO(Input Output)流
IO流用来处理设备之间的数据传输。
Java对数据的操作时通过流的方式。
Java用于操作流的对象都在IO包中。
流按操作数据分为两种:字节流与字符流。
流按流向分为:输入流,输出流。
字节流的抽象基类:
InputStream,OutputStream
字符流的抽象基类:
Reader,Writer
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream,Reader的子类FileReader。
需求:在硬盘上,创建一个文件并写入一些文字数据
找到一个专门用于操作文件的Writer子类对象,FileWriter。后缀名是父类名,前缀名是该流对象的功能。

import java.io.*;
class FileWriterDemo
{
 	public statci void main (String[] args) throws  IOException
 	{
  		//创建一个FileWriter对象。该对象一被初始化就必须明确被操作的文件.而且该文件会被创建到指定的目录下。如果该目录下已有同名文件,将被覆盖。其实该步就是在明确数据要存放的目的地。
  		FileWriter fw=new FileWriter("demo.txt");
 		 //调用write方法,将字符串写入到流中。
  		fw.write("abcd");
  		//刷新流对象中的缓冲数据,将数据刷新到目的地中
  		//fw.flush();
  		//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷新到目的地中。
  		//和flush()的区别:flush()刷新后流可以继续使用,close刷新后,会将流关闭。
 		 fw.close();
	 }
}

2、IO异常的处理方式
import java.io.*;
class FileWriterDemo2
{
 	public static void main(String[] args)
 	{
  		FileWriter fw=null;//在外面建立引用
  		try
  		{
   			FileWriter fw=new FileWriter("e:\\demo.txt");//在里面初始化
   			fw.write("aaa");
  		}
  		catch(IOException e)
  		{
   			System.out.println(e.toString());
  		}
  		finally
  		{
   			try
   			{
    				if(fw!=null)//关闭前对对象进行判断
   			 	fw.close();
   			}
   			catch(IOException e)
   			{
    				System.out.println(e.toString());
   			}  
  		}
 	}
}

3、文件的续写
import java.io.*;
class FileWriterDemo3
{
 	public static void main(String[] args)
 	{
  		//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处续写
  		FileWriter fw=null;//在外面建立引用
  		try
  		{
   			FileWriter fw=new FileWriter("e:\\demo.txt",true);//在里面初始化
  			 fw.write("bbb\r\nccc");//window下的回车符用\r\n;\n在linux下是换行
  		}
  		catch(IOException e)
  		{
   			System.out.println(e.toString());
 		 }
  		finally
  		{
   			try
   			{
   				 if(fw!=null)//关闭前对对象进行判断
    				 fw.close();
  			 }
   			catch(IOException e)
   			{
    				System.out.println(e.toString());
  			 }
   
  		}
 	}
}

4、文本文件读取方式一
import java.io.*;
class FileReaderDemo 
{
 	public static void main(String[] args) throws IOException
 	{
  		//创建一个文件读取流对象,和指定名称的文件相关联。要保证该文件是已经存在的,如果不存在,会发生异常FileNotFondException。
  		FileReader fr=new FileReader("demo.txt");
  		//调用读取流对象的read方法。
  		//read()方法一次只读一个字符,而且会自动往下读
  		int ch=0;
  		while(ch=fr.read()!=-1)
  		{
   			System.out.println((char)ch);
  		}
 		 fr.close();
	 }
}

5、文本文件读取方式二
通过字符数组进行读取
import java.io.*;
class FileReaderDemo2 
{
 	public static void main(String[] args) throws IOException
 	{
  		FileReader fr= new FileReader("demo.txt");
  		//定义一个字符数组,用于存储读到的字符
  		//该read(char[])返回的是读到的字符个数
  		char[] buf=new char[1024];//一般是1024的整数倍
  		int num=0;
  		while(num=fr.read(buf)!=-1)
  		{
   			System.out.println(new String(buf,0,num));
 		 }
 		 fr.close();
 	}
}

6、拷贝文本文件
将C盘一个文本文件复制到D盘.
复制的原理:
其实就是将C盘下的文件数据存储到D盘的一个文件中。
步骤:
(1)在D盘创建一个文件,用于存储C盘中的数据;
(2)定义一个读取流和C盘文件关联;
(3)通过不断的读写完成数据存储;
(4)关闭资源。
import java.io.*;
class CopyText
{
 	public static void main(String[] args) throw IOException
 	{
  		copy_1();
  		copy_2();//拷贝文本文件,全部读取放内存,在写入
 	}
 	public static void copy_2()
 	{
  		FilWriter fw=null;//局部变量都要初始化一下
  		FilReader fr=null;
  		try
  		{
   			fw=new FileWriter("SystemDemo_copy.txt");
   			fr=new FileReader("SystemDemo.java");
   			char[] buf=new char(1024);
  			 int len=0;
   			while((len=fr.Read())!=-1)
   			{
    				fw.write(buf,0,len);//写数组buf,从0开始,写len个
   			}
  		}
  		catch(IOException e)
  		{
   			throw new RuntimeException("读写失败");
 		 }
  		finally
  		{
   			if(fr!=null)
    			try
    			{
     				fr.close();
    			}
    			catch(IOException e)
    			{
     
    			}
   			 if(fw!=null)
    			try
    			{
    				fw.close();
    			}
    			catch(IOException e)
    			{
     
   			 }
  		}
 	}
 	//从C盘读一个字符,就往D盘写一个字符
	 public static void copy_1() throw IOExption
 	{
  		//创建目的地
  		FileWriter fw=new FileWriter("Demo_copy.txt");
  		//与已有文件关联
  		FileReader fr=new FileReader("Demo_copy.java");
  		int ch=0;
  		while((ch=fr.read())!=-1)
  		{
   			fw.write(ch);
  		}
  		fw.close();
  		fr.close();
 	}
}

7、newLine()

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

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

该缓冲区中提供了一个跨平台的换行符:newLine();

import java.io.*;
class BufferedWriterDemo
{
       publicstatic void main(String[] args) throws IOException
       {
              //创建一个字符写入流对象
              FileWriter fw=newFileWriter("buf.txt");
              //为了提高字符写入流效率。加入了缓冲技。
              //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可
              BufferedWriter bufw=newBufferedWriter(fw);
              bufw.write("abcde");
              bufw.newLine();//换行
              //只要用到缓冲区,就要记得刷新
              bufw.flush();
              //其实关闭缓冲区就是关闭缓冲区中的流对象
              bufw.close();
       }
}

8、readLine

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

readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。

import java.io.*;
class BufferedReaderDemo
{    
       publicstatic void main(String[] args) throws IOException
       {
              //创建一个读取流对象和文件相关联
              FileReader fr=newFileReader("buf.txt");
              //为了提高字符写入流效率。加入了缓冲技。
              //将字符读取对象作为参数传递给缓冲对象的构造函数
              BufferedReader bufr=newBufferedReader(fr);
              String line=null;
              while((line=bufr.readLine())!=null)
              {
                     System.out.println(line);
              }
              bufr.close();
       }
}

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

9、装饰设计模式

装饰设计模式

当想要对已有的对象进行功能增强时,可以定义一个类将已有对象传入,基于已有对象的功能并提供加强功能,那么自定义的该类就成为装饰类。比如上面模拟BufferedReader。

装饰类通常会通过构造方法接收被装饰对象,并基于被装饰对象,赋予更强的功能。

class Person
{
       publicvoid chifan()
       {
              System.out.println("吃饭");
       }
}
//对原有person类功能进行增强
class SuperPerson
{
       privatePerson p;
       SuperPerson(Personp)
       {
              this.p=p;
       }
       publicvoid superChifan()
       {
              System.out.println("酒");
              p.chifan();
              System.out.println("甜点");
       }
}
class PersonDemo
{
       publicstatic void main(String[] args)
       {
              Person p=new Person();
              //p.chifan();
              SuperPerson sp=new SuperPerson(p);
              sp.superChifan();
       }
}

装饰和继承的区别:

装饰模式比继承要灵活,避免了继承体系臃肿。而且降低了类与类之间的关系。

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。所以装饰类和被装饰类通常都属于一个体系中的。

10、字节流与字符流

字符流:FileReader FileWriter BufferedReader BufferedWriter

字节流:InputStream OutputStream

BufferedReader类中的子类LineNumberReader

FileReader fr=new FileReader("xx.text");
LineNumberReader lnr=newLineNumberReader(fr);
String line=null;
lnr.setLineNumber(100);//行号从100开始
while((line=lnr.readLine())!=null)
{
       System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();


读取键盘录入

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

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

键盘录入就是读一行数据的原理。也就是readLine方法。

但是readLine方法时字符流BufferedReader类中的方法。而键盘录入的read方法时字节流InputStream的方法。

import java.io.*;
class TransStreamDemo
{
       publicstatic void main(String[] args) throws IOException
       {
              //获取键盘录入对象
              InputStream in=Ssystem.in;
              //将字节流转换成字符流对象,使用转换流InputStreamReader
              InputStreamReader isr=newInputStreamReader(in);
              //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
              BufferedReader bufr=newBufferedReader(isr);
              //BufferedReader bufr=newBufferedReader(new InputStreamReader(System.in));可以代替上面三条语句
              //将一个文件的数据打印到控制台上
              //BufferedReader bufr=newBufferedReader(new InputStreamReader(newFileInputStream("CopyPic.java")));
              //OutputStreamWriter是字符流通向字节流的桥梁,字符转字节
              OutputStream out=System.out;
              OutputStreamWriter osw=newOutputStreamWriter(out);
              BufferedWriter bufw=new     BufferedWriter(osw);            
              //BufferedWriter bufw=newBufferedWriter(new OutputStreamWriter(System.out));
              //把键盘录入的数据存储到一个文件中
              //BufferedWriter bufw=newBufferedWriter(new OutputStreamWriter(newFileOutputStream("out.txt")));             
              String line=null;
              while((line=bufr.readLine())!=null)
              {
                     if("over".equals(line))
                            break;
                     osw.write(line.toUpuuerCase());
                     osw.newLine();
                     osw.flush();
              }
              bufr.close();
       }
}

11、流操作规律

流操作的基本规律

流对象有很多,不知道该用哪一个时,通过三个个明确来完成。

1、明确源和目的

源:输入流,InputStreamReader

目的:输出流,OutputStreamWriter

2、操作的数据是否是纯文本

是:字符流

不是:字节流

3、当体系明确后,在明确要使用哪个具体的对象

通过设备来区分:

原设备:内存,硬盘,键盘

目的设备:内存,硬盘,控制台


需求1:将一个文本文件中的数据存储到另一个 文件中

1)源:因为是源,所以使用读取流。InputStream Reader

是不是操作文本文件,是,这时就可以选择Reader,这样体系就明确了。

2)明确设备:硬盘。上的一个文件

Reader体系中可以操作文件的对象是FileReader

FileReader fr=newFileReader("a.txt");

3)是否需要提高效率:是。加入Reader体系中缓冲区BufferedReader

BufferedReader bufr=new BufferedReader(fr);

4)目的:OutputStreamWriter

是否是纯文本。是。Writer

5)设备:硬盘,一个文件

Writer体系中可以操作文件的对象FileWriter

FileWriter fw=newFileWriter("b.txt");

BufferedWriter bufw=new BufferedWriter(fw);


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

这个需求中有源和目的都存在。

1)源:InputStreamReader

是不是纯文本?是。Reader

2)设备:键盘。对应的对象是System.in

不是选择Reader吗?System.in对应的不是字节流吗?

为了操作键盘的文本数据方便,转成字符流按照字符串操作是最方便的。

所以既然明确了Reader,那么就将System.in转换成字符流。用了Reader体系中的转换流,InputStreamReader

InputStreamReader isr=newInputStreamReader(System.in);

3)需要提高效率吗?需要。BufferedReader

BufferedReader bufr=newBufferedReader(isr);

4)目的:OutputStreamWriter

是否是存文本?是。Writer

5)设备:硬盘,一个文件,使用FileWriter

FileWriter fw=newFileWriter("c.txt");

6)需要提高效率吗?需要

BufferedWriter bufw=new BufferedWriter(fw);

扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中

目的:OutputStreamWriter

是否是存文本?是。Writer

设备:硬盘。一个文件。使用FileWriter

但是FileWriter是使用的默认编码表,GBK

存储时,需要加入指定编码表uft-8.而指定的编码表只有转换流可以指定。

所以要使用的对象是OutputStreamWriter。

而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream outputStreamWriter osw=new OutputStreamWriter(newFileOutputStream(“d.txt”),”UTF-8”);

需要高效吗?需要。

BufferedWriter bufw=newBufferedWriter(osw);

所以记住,转换流什么时候使用,字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流。

class TransStreamDemo2
{
       publicstatic void main(String[] args) throws IOException
       {
              //改变默认的键盘源
              System.setIn(new FileInputStream(“xxx.java”));
              //目的可以可以改变
              System.setOut(new PrintStream(“zz.txt”));
//键盘的最常见写法
              BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
              BufferedWriter bufw=newBufferedWriter(new outputStreamWriter(new FileOutputStream(“d.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();
       }
}


GBK的用FileReader,new对象就可以读,UTF-8用转换流指定码表来读。

import java.io.*;
import java.util.*;
import java.text.*;
class ExceptionInfo
{
       publicstatic 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=newSimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
       				String s=sdf.format(d);
				PrintStream ps=new PrintStream(“exeception.log”);
      				 ps.println(s);
				System.setOut(ps);
			}
			catch(IOException ex)
			{
       				throw newRuntimeException(“日志文件创建失败”);
			}
			e.printStackTrace(System.out);
		}
	}
}

log4j工具——专门方便建立java的日志信息

//系统信息

//没有关流

import java.util.*;
class SystemInfo
{
       publicstatic void main(String[] args)throws IOException
       {
              Properties prop=System.getProperties();
              prop.list(new PrintStream(“sysinfo.txt”));
	}
}


你可能感兴趣的:(黑马程序员_IO输入与输出(1))