Java IO流学习总结五:转换流-InputStreamReader、OutputStreamWriter

Java IO流学习总结五:转换流-InputStreamReader、OutputStreamWriter

转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/54923506
本文出自【赵彦军的博客】

Java IO流学习总结一:输入输出流
Java IO流学习总结二:File
Java IO流学习总结三:缓冲流-BufferedInputStream、BufferedOutputStream
Java IO流学习总结四:缓冲流-BufferedReader、BufferedWriter
Java IO流学习总结五:转换流-InputStreamReader、OutputStreamWriter
Java IO流学习总结六:ByteArrayInputStream、ByteArrayOutputStream
Java IO流学习总结七:Commons IO 2.5-FileUtils

类的继承关系

Reader
|__ BufferedReader、StringReader、InputStreamReader
                                      |__ FileReader
                         
Writer
|__ BufferedWriter、StringWriter、OutputStreamWriter
                                      |__ FileWriter

InputStreamReader简介

InputStreamReader 是字符流Reader的子类,是字节流通向字符流的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如 GBK 等。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。一次只读一个字符。

  • InputStreamReader构造函数
InputStreamReader(Inputstream  in) //创建一个使用默认字符集的 InputStreamReader。

InputStreamReader(Inputstream  in,Charset cs) //创建使用给定字符集的 InputStreamReader。

InputStreamReader(InputStream in, CharsetDecoder dec) //创建使用给定字符集解码器的 InputStreamReader。

InputStreamReader(InputStream in, String charsetName)  //创建使用指定字符集的 InputStreamReader。

  • 一般方法
void  close() // 关闭该流并释放与之关联的所有资源。

String	getEncoding() //返回此流使用的字符编码的名称。

int	 read()  //读取单个字符。

int	 read(char[] cbuf, int offset, int length) //将字符读入数组中的某一部分。

boolean  ready() //判断此流是否已经准备好用于读取。

OutputStreamWriter简介

OutputStreamWriter 是字符流Writer的子类,是字符流通向字节流的桥梁。每次调用 write()方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。一次只写一个字符。

  • OutputStreamWriter构造函数
OutputStreamWriter(OutputStream out) //创建使用默认字符编码的 OutputStreamWriter

OutputStreamWriter(OutputStream out, String charsetName) //创建使用指定字符集的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, Charset cs) //创建使用给定字符集的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, CharsetEncoder enc) //创建使用给定字符集编码器的 OutputStreamWriter。
  • 一般方法
void  write(int c)   //写入的字符长度

void  write(char cbuf[])  //写入的字符数组

void  write(String str)  //写入的字符串

void  write(String str, int off, int len)  //应该写入的字符串,开始写入的索引位置,写入的长度

void  close() //关闭该流并释放与之关联的所有资源。

需要注意的事项

InputStreamReaderOutputStreamWriter实现从字节流到字符流之间的转换,使得流的处理效率得到提升,但是如果我们想要达到最大的效率,我们应该考虑使用缓冲字符流包装转换流的思路来解决问题。比如:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

实战演练,复制文本

package com.app;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

public class A5 {

	public static void main(String[] args) {
		String filePath = "F:/123.txt" ;
		String filePath2 = "F:/abc.txt" ;
		File file = new File( filePath ) ;
		File file2 = new File( filePath2 ) ;
		copyFile( file , file2 );

	}

	private static void copyFile( File oldFile , File newFile ){
		InputStream inputStream = null ;
		InputStreamReader inputStreamReader = null ;

		OutputStream outputStream = null ;
		OutputStreamWriter outputStreamWriter = null ;

		try {
			inputStream = new FileInputStream( oldFile ) ; //创建输入流
			inputStreamReader = new InputStreamReader( inputStream ) ; //创建转换输入流

			outputStream = new FileOutputStream( newFile ) ; //创建输出流
			outputStreamWriter = new OutputStreamWriter( outputStream ) ; //创建转换输出流

			int result = 0 ;

			while( (result = inputStreamReader.read()) != -1){  //一次只读一个字符
				outputStreamWriter.write( result ); //一次只写一个字符
			}

			outputStreamWriter.flush();  //强制把缓冲写入文件

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}finally{

			if ( outputStreamWriter != null) {
				try {
					outputStreamWriter.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if ( inputStreamReader != null ) {
				try {
					inputStreamReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}
}

效果图:

这里写图片描述


个人微信号:zhaoyanjun125 , 欢迎关注

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZmupUmT-1599192266094)(http://o7rvuansr.bkt.clouddn.com/weixin200.jpg)]

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java IO学习总结 Java操作有关的类或接口: Java类图结构: 的概念和作用 是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为的本质是数据传输,根据数据传输特性将抽象为各种类,方便更直观的进行数据操作。 IO的分类 根据处理数据类型的不同分为:字符和字节 根据数据向不同分为:输入和输出 字符和字节 字符的由来: 因为数据编码的不同,而有了对字符进行高效操作的对象。本质其实就是基于字节读取时,去查了指定的码表。 字节和字符的区别: 读写单位不同:字节以字节(8bit)为单位,字符以字符为单位,根据码表映射字符,一次可能读多个字节。 处理对象不同:字节能处理所有类型的数据(如图片、avi等),而字符只能处理字符类型的数据。 结论:只要是处理纯文本数据,就优先考虑使用字符。 除此之外都使用字节。 输入和输出 对输入只能进行读操作,对输出只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的Java IO对象 1.输入字节InputStreamIO 中输入字节的继承图可见上图,可以看出: InputStream 是所有的输入字节的父类,它是一个抽象类。 ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。 ObjectInputStream 和所有FilterInputStream 的子类都是装饰(装饰器模式的主角)。 2.输出字节OutputStream IO 中输出字节的继承图可见上图,可以看出: OutputStream 是所有的输出字节的父类,它是一个抽象类。 ByteArrayOutputStream、FileOutputStream 是两种基本的介质,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据, ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰。 3.字节的输入与输出的对应 图中蓝色的为主要的对应部分,红色的部分就是不对应部分。紫色的虚线部分代表这些一般要搭配使用。从上面的图中可以看出Java IO 中的字节是极其对称的。“存在及合理”我们看看这些字节中不太对称的几个类吧! LineNumberInputStream 主要完成从中读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始中有这样一个行号。在输出部分没有对应的部分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行号,看起来也是可以的。好像更不入了。 PushbackInputStream 的功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。 StringBufferInputStream 已经被Deprecated,本身就不应该出现在InputStream 部分,主要因为String 应该属于字符的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。 SequenceInputStream 可以认为是一个工具类,将两个或者多个输入当成一个输入依次读取。完全可以从IO 包中去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。 PrintStream 也可以认为是一个辅助工具。主要可以向其他输出,或者FileInputStream 写入数据,本身内部实现还是带缓冲的。本质上是对其它的综合运用的一个工具而已。一样可以踢出IO 包!System.out 和System.out 就是PrintStream 的实例! 4.字符输入Reader 在上面的继承关系图中可以看出: Reader 是所有的输入字符的父类,它是一个抽象类。 CharReader、StringReader 是两种基本的介质,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。 BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。 FilterReader 是所有自定义具体装饰的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。 InputStreamReader 是一个连接字节和字符的桥梁,它将字节转变为字符。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。 5.字符输出Writer 在上面的关系图中可以看出: Writer 是所有的输出字符的父类,它是一个抽象类。 CharArrayWriter、StringWriter 是两种基本的介质,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据, BufferedWriter 是一个装饰器为Writer 提供缓冲功能。 PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。 OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。 6.字符的输入与输出的对应 7.字符与字节转换 转换的特点: 其是字符和字节之间的桥梁 可对读取到的字节数据经过指定编码转换成字符 可对读取到的字符数据经过指定编码转换成字节 何时使用转换? 当字节和字符之间有转换动作时; 操作的数据需要编码或解码时。 具体的对象体现: InputStreamReader:字节到字符的桥梁 OutputStreamWriter:字符到字节的桥梁 这两个对象是字符体系中的成员,它们有转换作用,本身又是字符,所以在构造的时候需要传入字节对象进来。 8.File类 File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。 9.RandomAccessFile类 该对象并不是体系中的一员,其封装了字节,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。 该对象特点: 该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。 该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw) 注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件。
IO: Input Output 输入输出 自己去扩展: 1. 对象序列化和反序列化生成一个 2. 的种类: io包下 扩展nio包下 1. IO分类: 输入 输出 字节 InputStream(抽象类) OutputStream(抽象类) 字符 Reader (抽象类) Writer(抽象类) 2.字节:(重点) * 使用场景: * 1.字节处理除了文本、文字相关所有的问题,如,png/jpg/avi/map4/mp3/exe * 2.字符只处理文本、文字相关(编码乱码问题) * * 1.输入 abstract class InputStream:这个抽象类是表示输入字节的所有类的超类。 * | * FileInputStream 子类:文件字节输入 * 1. 构造方法 * FileInputStream(String name) name:表示(绝对路径、相对路径)文件名 * FileInputStream(File file) * * 2. 普通方法: //1. int read(byte[] b) 从输入读取一些字节数,并将它们存储到缓冲区 b 。 最常用 * //2. int read() 从输入读取数据的下一个字节。 //3. int read(byte[] b, int off, int len) 从输入读取最多 len字节的数据到一个字节数组。 * 2.输出 abstract class OutputStream:这个抽象类是表示输出字节的所有类的超类。 * | * FileOutputStream 子类:文件字节输出 * 1. 构造方法 FileOutputStream(String name) name:表示(绝对路径、相对路径)文件名 FileOutputStream(String name, boolean append) append:表示是否在该文件末尾追加数据,如果为true,表示追加,false,表示从头开始覆盖 * FileOutputStream(File file) FileOutputStream(File file, boolean append) * * 2. 普通方法: //1. void write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出。 最常用 * //2. void write(byte[] b)将 b.length个字节从指定的字节数组写入此文件输出。 //3. void write(int b) 将指定的字节写入此文件输出。 3. 注意事项: 1. 必须要关闭IO,节约资源开销 2. 关闭IO原则,先开后关 3. IO工具类的抽取,将所有的关(字节和字符)方法抽取出来,优化代码 4. 字符:(重点) * 使用场景:使用于处理文本相关的文件 * * Reader 抽象类: * |子类 * InputStreamReader(转换) * |子类 * FileReader:适用于读取字符相关的文件 * 1. 构造方法: * 1.FileReader(File file) 2.FileReader(String fileName) fileName:文件名(相对路径/绝对路径) * * 2. 读取方法: * 3. int read(char[] c)读取字符到char数组中 最常用 * 2. int read()读取一个字符 * 3. int read(char[] c,int start,int length)读取制定长度的字符到char数组中 * * Writer 抽象类: * |子类 * OutputStreamWriter转换) * |子类 * FileWriter:适用于写出字符相关的文件 * 1. 构造方法: * 1.FileWriter(File file) 默认是false 2.FileWriter(File file, boolean append) append:表示是在文件末尾追加还是从头覆盖,如果true追加,false覆盖,默认是false 3.FileWriter(String fileName) 默认是false 4.FileWriter(String fileName, boolean append) fileName:文件名(相对路径/绝对路径) * 2. 写出方法: * 1. public Writer append(CharSequence csq,int start,int end) * 2. public Writer append(char c) * 3. public Writer append(CharSequence csq) * 4. public void write(char[] c) * 5. public void write(String str) * 6. public void write(String str,int start,int end) 5. 乱码问题:(掌握) GBK: 中文2个字节 英文、数字:1字节 UTF-8: 中文3~6个字节 英文、数字:1字节 编码:将字符串转换为字节 * 1. byte[] getBytes() 根据默认字符集将当前字符串转换为字节数组 * 2. byte[] getBytes(String charsetName) UTF-8/GBK * 按照指定的字符集将将当前字符串转换为字节数组 * * 解码:将字节转换为字符 * 1.String(byte[] bytes, int offset, int length) * 根据默认字符集将字节数组中从指定下标开始到指定长度结束的数据转换为字符串 * * 2.String(byte[] bytes, int offset, int length, String charsetName) * 根据指定字符集将字节数组中从指定下标开始到指定长度结束的数据转换为字符串 * charsetName:字符集名 例如 : "GBK"、"UTF-8" 、"ISO-8859-1" * * 不常用 * 3.String(byte[] bytes) 根据默认字符集将字节数组转换为字符串 * 4.String(byte[] bytes, String charsetName) * 根据默认字符集将字节数组转换为字符串 * * 这里会有乱码问题: * 产生的原因: * 1、因为字符集不统一,即编码和解码new String(b,0,read,"gbk")字符集不一致 * 2、因为字节读取汉字的时候,字节数组长度不够,将一个汉字拆开了 * 解决: * 1. 用字符用统一的字符集(最常用) * * 浏览器 : UTF-8 * 前台: * HTML :UTF-8 * CSS :UTF-8 * JS、JSP :UTF-8 * * 后台: * java :UTF-8 * * 数据库: * mysql、oracle、DB2 :UTF-8 * * 开发工具:UTF-8 * 2. 文本文件用统一的字符集 且用字符读取和写出文本相关文件(最常用) * 3. 用一个大的字节数组(一般不用) 6. 转换:(重点) 目前唯一一个可以设置字符集的 (简单的理解为包装,就是将字节包装以下,方便操作文本相关的文件) * 使用场景: * 别人给提供了字节,而需要处理文本文件,这时候,就需要用转换转换一下,更方便处理文本文件 * * 作用:就是一字符的方式读取或写出文本相关的数据 * * InputStreamReader:将字节输入包装一下,让其更适合读取文本文件 * 构造方法: * 1.InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。 * 2.InputStreamReader(InputStream in, String charsetName) 创建一个使用指定字符集的InputStreamReader。 * 普通方法: * public int read(char[] cbuf) * int read(char[] cbuf, int offset, int length) * OutputStreamWriter:将字节输出包装一下,让其更适合写出文本文件 * 构造方法: * 1. OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。 * 2. OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用指定字符集的OutputStreamWriter。 普通方法: void write(char[] cbuf, int off, int len) append(CharSequence csq,int start,int end) 只有转换可以设置字符集 7. jdk7关的新方式: 用新结构可以自动关 前提:该必须是实现了一个接口 AutoCloseable 语法: try( //只能写创建的操作,不能写其他业务操作 ){ //可能有异常的代码 }catch(异常类型1 e){ }...不需要finally关了 8. 缓冲:(重点)包装 * 1.概念: 提高读取和写出效率的 * 2.作用: 提高效率 3.使用场景:以后一律都要使用,以提高效率 建议以后都是用字节或者字符数组的方式复制文件,这样效率最高 * 4. * BufferedInputStream * 字节输入缓冲构造方法: 1.BufferedInputStream(InputStream
IO从大的方向上分为字节和字符,包括四个抽象类: 1、输入:Reader, InputStream类型的子类(字符,字节) 2、输出:Writer, OutputStream类型的子类(字符,字节) 决定使用哪个类以及它的构造进程的一般准则如下(不考虑特殊需要): 第一,考虑最原始的数据格式是什么:是否为文本? 第二,是输入还是输出? 第三,是否需要转换:InputStreamReader, OutputStreamWriter? 第四,数据来源(去向)是什么:文件?内存?网络? 首先是字节: InputStream的实现类(System.in返回一个输入): 1)ByteArrayInputStream:ByteArrayInputStream的适配源是Byte数组,它有以下构造函数: ByteArrayInputStream(byte[] buf) 创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。 ByteArrayInputStream(byte[] buf, int offset, int length) 创建 ByteArrayInputStream,用byte 数组的第 off 个位置先后的 len 个位置buf 作为其缓冲区数组。 2)FileInputStream:FileInputStream的适配源是File对象,构造函数有: FileInputStream inFirst = new FileInputStream("test.txt");//默认工作站   File f = new File("test.txt"); FileInputStream inSecond = new FileInputStream(f); 3)PipeInputStream:通常用于进程间,构造函数有: PipedInputStream() PipedInputStream(PipedOutputStream out)直接连接到输出 4)SequenceInputStream:这个类可以将几个输入串联在一起合并为一个输入,构造函数有: SequenceInputStream(Enumeration e)枚举类型e中包含了若干个要被串联的输入 SequenceInputStream(InputStream s1, InputStream s2)先读取s1中数据。再读s2的数据。 以上能够直接对数据进行读和写的叫节点,但是直接用这些来操作是比较麻烦的,而且一个字节一个字节的对文件处理,对硬盘的读取和存入对硬盘的损伤是很大的,因此需要对这些节点进行包装,即外套一些处理来进行操作,InputStream有以下处理: 1) BufferedInputStream:带缓冲的输入,构造函数有: BufferedInputStream(InputStream in)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值