七.JAVA高级对象之IO流

目录

一、IO流概述

二、IO流的分类

1.Java IO类图

2.下面用一张表格详细讲解IO流的分类:

三.四个抽象基类

1.1.字节流

①概述:

②练习:

1.2.字节流缓冲区

2.1字符流

①. 字符流简介:

②.字符流读写:

思考:

2.2.缓冲区

扩展:了解装饰设计模式

四.流操作的基本规律

五.指定编码表(转换流可以指定编码表)


一、IO流概述

概述:
     IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数据传输,Java对于数据的操作都是通过流实现,而java用于操作流的对象都在IO包中。

分类:
     按操作数据分为:字节流和字符流。 如:InputStream和Reader
     按流向分:输入流和输出流。如:InputStream和OutputStream

IO流常用的基类:
      InputStream , OutputStream
字符流的抽象基类:
      Reader   , Writer

由上面四个类派生的子类名称都是以其父类名作为子类的后缀:
      如:FileReader和FileInputStream


二、IO流的分类

1.Java IO类图

2.下面用一张表格详细讲解IO流的分类:

分类

字节输入流

字节输出流

字符输入流

字符输出流

抽象基类

InputStream

OutputStream

Reader

Writer

访问文件

FileInputStream

FileOutputStream

FileReader

FileWriter

访问数组

ByteArrayInputStream

ByteArrayOutputStream

CharArrayReader

CharArrayWriter

访问管道

PipedInputStream

PipedOutputStream

PipedReader

PipedWriter

缓冲流

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter

转换流

   

InputStreamReader

OutputStreamWriter

对象流

ObjectInputStream

ObjectOutputStream

   

抽象基类

FilterInputStream

FilterOutputStream

FilterReader

FilterWriter

打印流

 

PrintStream

 

PrintWriter

特殊流

DataInputStream

DataOutputStream

   

以上流都是继承四个抽象基类:
字节输入流:InputStream           字符输入流:Reader
字节输出流:OutputStream        字符输出流:Writer

为了更好的学习Java流体系,下面主要先从四个抽象基类开始分析。


三.四个抽象基类

1.1.字节流

①概述:

1、字节流和字符流的基本操作是相同的,但是要想操作媒体流就需要用到字节流。
2、字节流因为操作的是字节,所以可以用来操作媒体文件。(媒体文件也是以字节存储的)
3、读写字节流:InputStream   输入流(读)和OutputStream  输出流(写)
4、字节流操作可以不用刷新流操作。
5、InputStream特有方法:
        int available();//返回文件中的字节个数
注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,
而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。
所以,此方法慎用,当文件不大时,可以使用。

②练习:

复制一张图片D:\\Program app.zip到F:/Ba.rar

实现方式有两种:单字节输入输出流(int),多字节输入输出流(byte[]),具体代码如下

package com.bdsw.wxl.day9.homework;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
 * 
 * @author 王雪亮
 * @date 2018年7月24日
 * @Description 测试FileInputStream,FileOutputStream,BufferedInputStream
 *                  BufferedOutputStream两个类的实现文件的复制
 *                  
 *       ①singleBStream:   单字节实现文件的复制
 *       ②mulCharTest:       多字节实现文件的复制
 *       ③bufReader:           单字节缓冲区实现文件的复制
 */
import java.io.InputStream;
public class FileTest {
	
	/**
	 *@function  单字节实现文件的复制
	 *@param s1    将复制的文件的路径
	 */
	// 17.4M需要12s
	static void singleBStream(String s1) throws Exception {
		try {
			long l1 = System.currentTimeMillis();
			
			//1.定义文件输入输出流
			FileInputStream fis = new FileInputStream(s1);
			FileOutputStream fos = new FileOutputStream("F:\\aaa.zip");
			int l = 0;
			
			//2.循环从fis中读一个字节并复制到fos中,直到完成复制
			while ((l = fis.read()) != -1) {
				fos.write(l);
			}
			long l2 = System.currentTimeMillis();
			
			//3.打印所需时间
			System.out.println("需要" + (l2 - l1) / 1000 + "s");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 *@function  多字符实现文件的复制
	 *@param s1    将复制的文件的路径
	 */
	//17.4M 需要0s
	static void mulBStream(String s1) throws Exception {
		try {
			long l1 = System.currentTimeMillis();
			
			//1.定义文件输入输出流
			FileInputStream fis = new FileInputStream(s1);
			FileOutputStream fos = new FileOutputStream("F:\\aaa.rar");
			
			int len = 0;
			byte[] bt = new byte[1000];
			
			//2.循环将fis中的数据读入字节数组bt,直到fis中的元素读完
			while ((len = fis.read(bt)) != -1) {
				//3.将字节数组bt中的内容写到fos中
				fos.write(bt, 0, len);
			}
			long l2 = System.currentTimeMillis();
			
			//4.打印所需时间
			System.out.println("需要" + (l2 - l1) / 1000 + "s");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

	}
	
	
	public static void main(String[] args) throws Exception {
		String s1 = "D:\\Program app.zip";
		singleBStream(s1);//单字节复制文件
		mulBStream(s1);//多字节复制
	}
}

1.2.字节流缓冲区

* 字节流缓冲区跟字符流缓冲区一样,也是为了提高效率。
注意事项:
1. read():会将字节byte()提升为int型值
2. write():会将int类型转换为byte()类型,保留最后的8位。

练习:使用缓冲区方式,实现上述功能

代码如下:

package com.bdsw.wxl.day9.homework;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
 * 
 * @author 王雪亮
 * @date 2018年7月24日
 * @Description   BufferedInputStream,BufferedOutputStream两个类的实现文件的复制
 *                  
 *                  
 *       ③bufReader:           单字节缓冲区实现文件的复制
 */
import java.io.InputStream;
public class FileTest {
	
	 //**
	 *@function  多字节缓冲区实现文件的复制
	 *@param s1    将复制的文件的路径
	 *//*
	static void buffStream(String s1) throws Exception {
		//1.定义文件输入输出流in,out
		FileInputStream in;
		FileOutputStream out;
		try {
			long l1 = System.currentTimeMillis();
			
			//2.为文件输入输出流赋值,
			in = new FileInputStream(s1);
			out=new FileOutputStream("F:/Ba.rar");
			//3.用文件输入输出流构造文件输入输出流缓冲区
			BufferedInputStream bis=new BufferedInputStream(in);
			BufferedOutputStream bos=new BufferedOutputStream(out);
			
			int len;
			byte []bt=new byte[100];
			
			//4.循环将bis中的数据读入字符数组bt,直到bis中的元素读完
			while((len=bis.read(bt))!=-1) {
				//5.将字节数组bt中的内容写到bos中
				bos.write(bt,0,len);
			}
			
			long l2 = System.currentTimeMillis();
			
			//6.打印复制所需时间
			System.out.println("缓冲区需要" + (l2 - l1) / 1000 + "s");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		String s1 = "D:\\Program app.zip";
		buffStream(s1); //多字节缓冲区复制文件
	}
}

2.1字符流

①. 字符流简介:

* 字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。
* 字符流只用来处理文本数据,字节流用来处理媒体数据。
* 数据最常见的表现方式是文件,字符流用于操作文件的子类一般是FileReader和FileWriter。

②.字符流读写:

注意事项:
* 写入文件后必须要用flush()刷新。
* 用完流后记得要关闭流
* 使用流对象要抛出IO异常
* 定义文件路径时,可以用“/”或者“\\”。(具体区别已在上一篇博客中说明)
* 在创建一个文件时,如果目录下有同名文件将被覆盖。
* 在读取文件时,必须保证该文件已存在,否则出异常

思考:

通过字符流的方式,实现字节流中的例题(通过int和char[]两种形式分别自己实现)

2.2.字符缓冲区

 字符流的缓冲区:BufferedReader和BufferedWreiter
* 缓冲区的出现时为了提高流的操作效率而出现的.
* 需要被提高效率的流作为参数传递给缓冲区的构造函数
* 在缓冲区中封装了一个数组,存入数据后一次取出

综合练习

分别使用字节流和字符流两种方式,实现对F:\\a.jpg图像进行等份切割,再将等份切割的图像合并成一张新的图像
*思考两种切割方式结果不同的原因

package com.bdsw.wxl.day9.homework;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
/**
 * 
 * @author 王雪亮
 * @date 2018年7月24日
 * @Description  字节流和字符流分别切割并合并文件(图像为例)
 *    
 *      ①byteDepart:  字节流切割文件
 *      ②byteFit:         将字节流分割图像合并
 *      ③charDepart:  用字符流分割图像
 *      ④charFit:         将字符流分割图像合并
 */
public class DepartFile {
	/**
	 *@function   用多字节流分割图像
	 *@param s1       需要切割文件的路径
	 */
	static void byteDepart(String s1) throws Exception {
		try {
			//1.字节流方式定义被切割文件对象
			FileInputStream fis=new FileInputStream(s1);
			
			int i=0;   //用于构造切割图像的文件名
			int len=0; //存放字节数组返回的大小
			byte[] bt=new byte[50*1024]; //存放读的多个字节数据
			
			//2.循环读fis对象文件中的数据,一次读取len大小个字节
			while((len=fis.read(bt))!=-1) {
				
				//3.定义切割成的文件对象
				FileOutputStream fos=new FileOutputStream("F:\\a"+i++ +".jpg");
				
				//4.将字节流中的数据写入切割成的对象fos中
				fos.write(bt, 0, len);
				
				//5.关闭文件
				fis.close();
				fos.close();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 *@function 将多字节流分割的图像合并
	 */
	static void byteFit() throws Exception {
		//1.定义合并成的文件 对象
		FileOutputStream fos=new FileOutputStream("F:/aa.jpg");
		try {
			int i;//用于构造切割图像的文件名
			
			for(i=0;i<7;i++) {
				
				//2.定义切割的图像名字,并生成相应对象
				String src="F:\\a"+i+".jpg";
				FileInputStream fis=new FileInputStream(src);
				
				int len=0; //存放字节数组返回的大小
				byte[] b=new byte[1024*50];//存放切割图像的字节数组
				
				//3.将字节数组的内容循环写入合并成的文件
				while((len=fis.read(b))!=-1) {
					fos.write(b, 0, len);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 *@function   用多字符流分割图像
	 *@param s2       需要切割文件的路径
	 */
	static void charDepart(String s2) throws Exception {
		try {
			//1.字符流方式定义被切割文件对象
			FileReader fr=new FileReader(s2);
			
			int i=0;     //用于构造切割图像的文件名
			int len=0;   //存放字符数组返回的大小
			char bf[]=new char[1024*50]; //存放读的多个字符数据
			
			//2.循环读fr对象文件中的数据,一次读取len大小个字符
			while((len=fr.read(bf))!=-1) {
				
				//3.定义切割成的文件对象
				FileWriter fw=new FileWriter("F:/b"+i+++".jpg");
				fw.write(bf, 0, len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 *@function 将多字符流分割的图像合并
	 */
	static void charFit() throws Exception {
		//1.定义合并成的文件 对象
		FileWriter fw=new FileWriter("F:/bb.jpg");
		try {
			int i; //用于构造切割图像的文件名
			
			for(i=0;i<6;i++) {
				
				//2.定义切割的图像名字,并生成相应对象
				String src="F:\\b"+i+".jpg";
				FileReader fis=new FileReader(src);
				
				int len=0;//存放字符数组返回的大小
				char[] b=new char[1024*50]; //存放切割图像的字符数组
				
				//3.将字符数组的内容循环写入合并成的文件
				while((len=fis.read(b))!=-1) {
					fw.write(b,0,len);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		//1.定义需要切割图片的路径
		String s1 = "F:\\a.jpg";
		String s2 = "F:\\b.jpg";
		
		try {
			byteDepart(s1);//2.1字节方式切割图片
			byteFit();//3.1将字节切割的图片合并
			
			charDepart(s2);//2.2字符方式切割图片
			charFit();//3.2将字符切割的图片合并
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

扩展:了解装饰设计模式


四.流操作的基本规律

/*  
流操作的基本规律。  
一、两个明确:(明确体系)  
1. 明确源和目的  
    源:输入流  InputStream  Reader  
    目的:输出流  OutputStream Writer  
  
2. 操作的数据是否是纯文本  
    是: 字符流  
    否: 字节流  
二、明确体系后要明确具体使用的对象  
    通过设备区分:内存,硬盘,键盘  
    目的设备:内存,硬盘,控制台  
  
  
示例1:将一个文本文件中的数据存储到另一个文件中: 复制文件  
    一、明确体系  
        源:文件-->读取流-->(InputStream和Reader)  
        是否是文本:是-->Reader  
          
          
        目的:文件-->写入流-->(OutputStream Writer)  
        是否纯文本:是-->Writer  
      
    二、 明确设备  
        源:Reader  
            设备:硬盘上一个文本文件 --> 子类对象为:FileReader  
                FileReader fr = new FileReader("Goods.txt");  
              
            是否提高效率:是-->加入Reader中的缓冲区:BufferedReader  
                BufferedReader bufr = new BufferedReader(fr);  
                  
        目的:Writer  
            设备:键盘上一个文本文件 --> 子类对象:FileWriter  
                FileWriter fw = new FileWriter("goods1.txt");  
            是否提高效率:是-->加入Writer的缓冲区:BufferedWriter  
                BufferedWriter bufw = new BufferedWriter(fw);  
              
              
              
示例2:将一个图片文件数据复制到另一个文件中:复制文件  
    一、明确体系  
        源:文件-->读取流-->(InputStream和Reader)  
        是否是文本:否-->InputStream  
          
          
        目的:文件-->写入流-->(OutputStream Writer)  
        是否纯文本:否-->OutputStream  
      
    二、 明确设备  
        源:InputStream  
            设备:硬盘上一个媒体文件 --> 子类对象为:FileInputStream  
                FileInputStream fis = new FileInputStream("Goods.txt");  
              
            是否提高效率:是-->加入InputStream中的缓冲区:BufferedInputStream  
                BufferedInputStream bufi = new BufferedInputStream(fis);  
                  
        目的:OutputStream  
            设备:键盘上一个媒体文件 --> 子类对象:FileOutputStream  
                FileOutputStream fos = new FileOutputStream("goods1.txt");  
            是否提高效率:是-->加入OutputStream的缓冲区:BufferedOutputStream  
                BufferedOutputStream bufo = new BufferedOutputStream(fw);  
  
示例3:将键盘录入的数据保存到一个文本文件中  
    一、明确体系  
        源:键盘-->读取流-->(InputStream和Reader)  
        是否是文本:是-->Reader  
          
          
        目的:文件-->写入流-->(OutputStream Writer)  
        是否纯文本:是-->Writer  
      
    二、 明确设备  
        源:InputStream  
            设备:键盘 --> 对用对象为:System.in --> InputStream  
                为了操作方便,转成字符流Reader --> 使用Reader中的转换流:InputStreamReader  
                InputStreamReader isr = new InputStreamReader(System.in);  
              
            是否提高效率:是-->加入Reader中的缓冲区:BufferedReader  
                BufferedReader bufr = new BufferedReader(isr);  
                  
        目的:Writer  
            设备:键盘上一个文本文件 --> 子类对象:FileWriter  
                FileWriter fw = new FileWriter("goods1.txt");  
            是否提高效率:是-->加入Writer的缓冲区:BufferedWriter  
                BufferedWriter bufw = new BufferedWriter(fw);  

五.指定编码表(转换流可以指定编码表)

要求:用UTF-8编码存储一个文本文件

import java.io.*;  
public class IOStreamLaw {  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) throws IOException {  
                //键盘的最常见写法  
                BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  
                BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("goods1.txt"),"UTF-8"));  
                String line = null;  
                while((line=bufr.readLine())!=null){  
                    if("over".equals(line)) break;  
                    bufw.write(line.toUpperCase());  
                    bufw.newLine();  
                    bufw.flush();  
                }  
                bufr.close();  
    }  
  
  
}  

文章主要参考:JAVA IO流最详解

猜你喜欢

转载自blog.csdn.net/qq_34082113/article/details/81195236
今日推荐