黑马程序员--------java IO流 Reader、Writer、InputStream、OutputStream

----------- android 培训 java培训 、java学习型技术博客、期待与您交流!------------
IO流

1、流的分类:

  1)输入流(读)和输出流(写)

  2)按处理数据的不同可以分为字符流和字节流

2、字节流:处理字节数据的流对象。设备上的媒体文件、图片、文本文件,它们都已二进制方式存储,二进制最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元是byte。意味着字节流可以处理设备上的所有数据,所以字节流也可以处理字符数据

3、字符流:每个国家都不一样,所以涉及到了字符编码问题,GBK编码的中文用unicode编码解析是有问题的,所以中文字节数据的同时+指定的编码表才可以解析正确的数据。为了方便文字的解析,将字节流和编码封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流

4、流的体系:一共4个基类,它们的子类都有一个共性特点——子类名后缀都是父类名,前缀名都是这个子类的功能名称

   字节流:InputStream  OutputStream

   字符流:Reader  Writer

 

Writer字符流:

   |——BufferedWriter:将文本写入字符输出流缓冲区,从而提高单个字符、数组和字符串的高效写入

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

      |——FileWriter:用来写入文的便捷类,此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可以接受的。要自己指定这些值,可以先在FileOutputStream上构造一个OutputStreamWriter

   |——PrintWriter:字符打印流

   |——CharArrayWriter:

   |——StringWriter:

1、操作方式

   public static void main(String[] args)throws IOException{ //读写都会发生IO异常

   /*

   1:创建一个字符输出流对象,用于操作文件。该对象一建立,就必须明确数据存储的位置,是一个文件

   2:对象产生后,会在对内存中有一个实体,同时也调用系统底层资源,在指定位置创建一个存储数据的文件

   3:如果指定位置出现同名文件文件会被覆盖,如果指定位置不存在则会报异常

   */

   FileWriter fw = new FileWriter(“d:\\abc.txt”);//FileNotFoundException

   /*

   调用Writer类中的方法write写入数据,数据并未写入到目的地,而是写入到了流中(内存缓冲区中),需要在调用方法flush 将数据刷新到目的地

   */

   fw.write(“你好”);

   fw.flush();//将流中数据刷新到目的地

   fw.close();//关闭输出流。在关闭之前close也会刷新该流

   }

close()flush()的区别:

flush():刷新缓冲区,将缓冲区的数据刷到目的地,流可以使用

close():先将缓冲区数据刷到目的地,再关闭流,该方法用于结束调用底层资源,这个动作一定要做,一般写在finally语句里面

close():先将缓冲区数据刷到目的地,再关闭流,该方法用于结束调用底层资源,这个动作一定要做,一般写在finally语句里面

2、FileWriter写入数据的细节:

  1)Windows系统中的换行符为:\r\n两个符号组成。 Linux:\n

  2)在已有的文件中续写数据,只需要在FileWriter 构造函数的文件目的地后面再添加一个参数true即可

  3)目录分隔符:Windows “ \\ 
//需求:在硬盘上创建一个文件,并写一些文字数据
import java.io.*;
class  FileWriterDemo11
{	   public static void main(String[] args)
	   {
	   	   FileWriter fw = null;
	       try
	       {
			  fw = new FileWriter("f:\\abcde.txt",true);//如果文件里面已有内容,直接在内容的最后开始添加
			  fw.write("12345"+"\r\n");//\r\n 为换行符
			  fw.write("上山打老虎");
			  fw.flush();//将流中的数据刷新到文件里面	
	       }
	       catch (IOException e)
	       {
			  throw new RuntimeException("写入的文件不存在");
	       }
		   finally//操作执行后一定要关闭流资源,所以将fw.close写在finally里面
		   {
			   try//close也会抛出IO异常,必须对其进行处理
			   {
				  if(fw!=null)//当上面指定的文件目录不存在时,fw创建文件不成功。如果不判断fw是否为空,执行时会出现空指针异常
					   fw.close();//关闭流	
			   }
			   catch (IOException e)
			   {
				  throw new RuntimeException("创建输出流失败"); 
			   }
		   }
	    }
}

3、BufferedWriter:是给字符输出流提高效率的,那就意味着,缓冲区对象建立时,就必须要先有流对象,

明确要提高具体的流对象的效率

   FileWriter fw = new File(“c:\\abc.txt”);

   BufferedWriter bw = new BufferedWriter(fw);//让缓冲区和指定流相关联

   bw.write(“kkkk”);

   bw.newLine();//跨平台换行语句

   bw.flush();//使用缓冲区是必须要写刷新

   bw.close();//关闭缓冲区,其实就是在关闭具体的流

 

Reader字符流:

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

可以指定缓冲区的大小,或者可以使用默认大小。大多数情况下,默认值就足够打了

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

   |——InputStreanReader:是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字

它使用的字符集可以有指定名称或显示给定,或者可以接受平台默认的字符集

     |——FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。

   |——CharArrayReader:

   |——StringReader:

 

1、操作方式:使用FileReader,读取一个文本文件中的数据。返回-1,标志读到结尾

 方式一
   import java.io.*;
class  FileReaderDemo {
	  public static void main(String[] args) throws IOException {
		/*
		创建可以读取文本文件的流对象,FileReader让创建好的流对象和指定的文件相关联。
		*/
		FileReader fr = new FileReader("demo.txt");
		int ch = 0;
		while((ch = fr.read())!= -1) { //条件是没有读到结尾
			System.out.println((char)ch); //调用读取流的read方法,读取一个字符。
		}
		fr.close();
	  }
}
————————————————————————————
读取数据的第二中方式:自定义数组缓冲区,较为高效
import java.io.*;
class FileReaderDemo2 {
	   public static void main(String[] args) throws IOException {
		  FileReader fr = new FileReader("demo.txt"); //创建读取流对象和指定文件关联。
		  //因为要使用read(char[])方法,将读取到字符存入数组。所以要创建一个字符数组,一般数组的长度都是1024的整数倍。
		  char[] buf = new char[1024];
		  int len = 0;
		  while(( len=fr.read(buf)) != -1) {
			System.out.println(new String(buf,0,len));
		  }
		  fr.close();
	    }
}

2、BufferedReader:字符读取流缓冲区,提高读取效率,可以整行读取

  FileReader fr = new FileReader(“c:\\abc.txt”);//创建一个字符读取流,并关联一个文件

  BufferedReader br = new BufferedReader(fr);//将读取流与缓冲区关联

   String line = null;

  while((line = br.readLine())!=null){ //readLine方法返回时是不带换行符的

       System.out.println(line);

   }

  br.close();

3、 要点:读取键盘录入常见写法,通过转换流   控制台打印输出也可以使用缓冲区写法(转换流)

   BufferedReader br = newBufferedReader(new InputStreamReader(System.in));//读取键盘录入

   BufferedWriter bw = new BufferedWtiter(newOutputStreamWriter(System.out));//输出到控制台

   String line =null;

   while((line=br.readLine())!=null){

      if(line.equals(“end”))

           break;

   bw.write(line.toUpperCase());//将键盘输入字母转换为大写打印

   bw.newLine();//换行

   bw.flush();

   }

   br.close();

   bw.close();

IO中的使用到了一个设计模式:装饰设计模式。

装饰设计模式解决:对一组类进行功能的增强。

包装:写一个类(包装类)对被包装对象进行包装;

 * 1、包装类和被包装对象要实现同样的接口;

 * 2、包装类要持有一个被包装对象;

 * 3、包装类在实现接口时,大部分方法是靠调用被包装对象来实现的,对于需要修改的方法我们自己实现

 

InputStream字节流

   |——FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境

FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

   |——FilterIputStrean:包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。

     |——BufferedInputStream:该类实现缓冲的输入流

     |——Stream

   |——ObjectInputStream:

   |——PipedInputStream:管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从PipedInputStream对象读取,并由其他线程将其写入到相应的PipedInputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏

 

OutputStream字节流

   |——FileOutputStream:文件输入流是用于将数据写入 File或者FileDescriptor的输出流

   |——FilterOutputStream:此类是过滤输出流的所有类的超类

      |——BufferedOutputStream:该类实现缓冲区的输出流

      |——PrintStream:字节打印流

      |——DataOutputStream:

   |——ObjectOutStream:

   |——PipedOutputStream:

流的操作规律:重点

1、源:键盘录入

   目的:控制台 

2、需求:把键盘录入的数据存储到一个文件中

   源:键盘

   目的:文件

3、需求:想要将一个文件的数据打印在控制台上

   源:文件

   目的:控制台

********************************

流操作的基本规律:通过三个明确来完成,该怎么使用流对象

1、明确源和目的:

   源:输入流    InputStream   Reader

   目的:输出流  OutputStream Writer

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

   是:字符流

   不是:字节流

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

   通过分析设备来进行区分:

   源设备:内存、硬盘、键盘

   目的  :内存、硬盘、控制台

***********************************

示例:

1、将一个文本文件中数据存储到另一个文件中。复制文件

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

   是不是操作文本文件。

   是: 这时就可以选择字符流Reader

   这样体系就明确了

   接下来要明确使用体系中的哪个对象。

   明确设备:硬盘 。一个文本文件

  Reader可以操作文件的对象时 FileReader

   是否需要提高效率:是! 就要加入Reader体系中的缓冲区BufferedReader

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

   BufferedReader br = new BufferedReader(fr)

 

   目的:OutputStream   Writer

   是否是纯文本。

   是!Writer

   设备:硬盘,一个文件

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

   是否需要提高效率:是!加入Writer体系中的缓冲区BufferedWriter

   FileWriter fw = new FileWriter("aa.txt");

   BufferedWriter bw = new BufferedWriter(fw);

 

2、需求:将键盘录入的数据保存到一个文件中,这个需求源和目的都存在,那么怎么分析

 

   源:InputStrean   Reader

   是不是纯文本?是Reader

   设备:键盘,对应的对象是System.in

   System.in对应的是字节流,而Reader是字符流

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

   所以,既然明确了Reader,那么就要将System.in转成Reader

   所以要使用Reader体系中的转换流InputStreamReader

   InputStreamReader isr = new InputStreamReader(System.in);

   需要提高效率吗?是!BufferedReader

   BufferedReader br = newBufferedReader(isr);

 

   目的:OutputStream   Writer

   是不是纯文本?是  Writer

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

   FileWriter fw = new FileWriter("e:\\abc.txt");

   是否需要提高效率?是BufferedWriter  

   BufferedWriter bw = new BufferedWriter(fw);

  **************************************************

   扩展:想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中,要使用到转换流。对键盘录入数据进行操作时也需要使用到转换流System.in

   目的:OutputStream   Writer

   是否是纯文本:是  Writer

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

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

 

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

   所以要使用OutputStreamWriter

   而该转换流要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream

  OutputStreamWriter osw = new OutputStreamWriter(newFileOutputStream("e:\\ccc.txt"),"utf-8");

 

   需要提高效率吗?是  BufferedWriter

  BufferedWriter bw = new BufferedWriter(osw);

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

/*
练习1:将一个图片文件中数据存储到另一个文件中。复制图片文件。要按照思路格式自己完成3个明确


思路:
1、源:为输入流 可以使用 InputStream  Reader
   设备:硬盘,一个文件
   是否问纯文本文件?
   否!那就选择字节流输入Input体系中能操作媒体文件的对象是 FileInputStream
   是否要增强操作
   是:可以加入字节流缓冲技术 BufferedInputStream

	FileInputStream fis = new FileInputStream("e:\\a1.jpg");
	BufferedInputStream bis = new BufferedInputStream("fis");

2、目的:为输出流,可以使用 OutputStream  Writer
   设备:硬盘,一个文件
   是否为纯文本文件
   否:那就选择OutputStream体系中操作媒体文件的对象 FileOutputStream
   是否需要增强操作
   是:可以加入缓冲技术 BufferedOutputStream

   FileOutputStream fos = new FileOutputStream("e:\\a2.jpg");
   BufferedOutputStream bos = new BufferedOutputStream(fos);
*/
import java.io.*;
class TransStreamTest1
{
	public static void main(String[] args) throws IOException
	{
		FileInputStream fis = new FileInputStream("e:\\a1.jpg");
		BufferedInputStream bis = new BufferedInputStream(fis);

		FileOutputStream fos = new FileOutputStream("e:\\a2.jpg");
		BufferedOutputStream bos = new BufferedOutputStream(fos);

		byte[] by = new byte[1024];
		int x =0;
		while((x=bis.read(by))!=-1)
		{
			bos.write(by,0,x);//数组里面存储多少个数据就写多少个数据
			bos.flush();
		}
		bis.close();
		bos.close();
	}
}

/*
练习2:将一个文本数据打印在控制台上。要求按照格式自己完成3个明确

思路:
源:为输入流  InputStream  Reader
设备:硬盘,一个文件
是不是纯文本数据?是: Reader
可以使用Reader类中操作文本的对象FileReader
FileReader fr = new FileReader("CopyMp3.java");
是否要提高效率?是  BufferedReader
BufferedReader br = new BufferedReader(fr);

目标:为输出流 OutputStream  Writer
设备:控制台,一个文件
是不是村文本文件?是 Writer
可以使用Writer类中操作文本的对象 FileWriter
FileWriter fw = new Filewriter(System.out)
是否要提高效率?是  BufferWriter
BufferedWriter bw = newBufferedWriter(fw);
*/
import java.io.*;
class TransStreamTest2 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("CopyMp3.java");
		BufferedReader br = new BufferedReader(fr);
		OutputStreamWriter fos = new OutputStreamWriter(System.out);
		
		BufferedWriter bw = new BufferedWriter(fos);
		
		char[] arr = new char[1024];
		int x=0;
		while((x=br.read(arr))!=-1)
		{
			bw.write(arr,0,x);
			bw.flush();
		}
		
		/*
		//每次读写一行的数据
		String s ="";
		while((s=br.readLine())!=null)
		{
			bw.write(s);
			bw.newLine();
			bw.flush();
		}
		*/
		br.close();
		bw.close();
	}
}

/*
练习:在控制台输入一段字符,并打印出来
思路:
源:输入流 InputStream  Reader
是否为纯文本文件?是 用Reader
设备:控制台,System.in
由于System.in是字节流对象,而确定使用Reader,则需要将字节流转换为字符流
InputStreamReader isr = new InputStreamReader(System.in);
是否需要提高效率?是 BufferedReader
BufferedReader br = BufferedReader(isr);

目的:输出流 OutputStream   writer
是否为纯文本文件?是 Writer
设备:控制台 ,System.out
由于System.out是字节流输出对象,需要将字符流转换为字节流进行输出
OutputStreamWriter osw = new OutputStreamWriter(System.out);
是否需要提高效率?是 BufferedWriter
BufferedWriter bw = newBufferedWriter(osw);

*/
import java.io.*;
class TransStreamTest3 
{
	public static void main(String[] args) throws IOException
	{
		//method1();
		method2();
	}
	public static void method2()
	{
		BufferedReader br =null;
		BufferedWriter bw = null;
		try
		{
			br = new BufferedReader(new InputStreamReader(System.in));
			bw = new BufferedWriter(new OutputStreamWriter(System.out));
			String s = null;
			while((s=br.readLine())!=null)
			{
				if("end".equals(s))
					break;
				bw.write(s);//将数据写入流
				bw.newLine();//换行
				bw.flush();//刷新到指定目的
			}
		}
		catch (IOException e)
		{
			System.out.println("输入、输出文件失败");

		}
		finally
		{
			try
			{
				if(br!=null)
					br.close();
			}
			catch (IOException e)
			{
				System.out.println("关闭输入流失败");
			}
			try
			{
				if(bw!=null)
					bw.close();
			}
			catch (IOException e)
			{
				System.out.println("关闭输出流失败");
			}
		}
	}

/*
将控制台输入的数据存储到一个.txt的文件里面,使用utf-8编码表
思路:
源:输入流 InputStream   Reader
是否为纯文本? 是  使用Reader
设备:控制台,需要使用System.in对象
由于System.in是属于字节流,所以需要将字节流转换为字符流 InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in)
是否需要提高效率? 是  BufferedReader
BufferedReader br = new BufferedReader(isr);

目的:输出流 OutputStream  Writer
是否为纯文本文件,是 使用Writer
设备:硬盘,一个文件 
但是需要使用指定的编码表utf-8,而字符流默认的是GBK,所以转为字节流来操作
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("e:nba.txt"),"utf-8");
是否需要提高效率? 是 BufferedWriter
BufferedWriter bw = new BufferedWriter(osw);
*/
import java.io.*;
class TransStreamTest4 
{
	public static void main(String[] args)throws IOException 
	{
		System.setIn(new FileInputStream("CopyMp3.java"));//更改默认键盘输入流
		//System.setOut(PrintStream out) 可以更改默认打印流(默认为控制台)
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("e:\\nbb.txt"),"GBK");
		BufferedWriter bw = new BufferedWriter(osw);
		String s = null;
		while((s=br.readLine())!=null)
		{
			if("end".equals(s))
				break;
			bw.write(s);
			bw.newLine();
			bw.flush();
		}
		br.close();
		bw.close();
	}
}

-----------android培训java培训、java学习型技术博客、期待与您交流!------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值