IO流输入 输出流 字符字节流
一、流
1.流的概念
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
2.流的分类
根据处理数据类型的不同分为:字符流和字节流,字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。
根据数据流向不同分为:输入流和输出流
3.字符流和字节流
3.1 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换。
3.2 字节流和字符流的区别:
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,我们将在下面验证这一点。
结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。从效率而言,字符流(一次可以处理一个缓冲区)一次操作比字节流(一次一个字节)效率高。
4.输入流和输出流
对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。输入输出流的流向是相对于程序而言。
输入流:InputStream 读入 就是从外部文件中读取数据到程序。对应 Reader;
输出流: OutputStream 写出 就是将数据从程序写入到外部文件。对应 Writer;
二、字节流
1.字节流概述
1)字节流和字符流的基本操作是相同的,但是要想操作媒体流就需要用到字节流。
2)字节流因为操作的是字节,所以可以用来操作媒体文件。(媒体文件也是以字节存储的)
3)读写字节流:InputStream 输入流(读)和OutputStream 输出流(写)
4)字节流操作可以不用刷新流操作。
5)InputStream特有方法:
int available(); //返回文件中的字节个数
注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。所以,此方法慎用,当文件不大时,可以使用
2. 字节流缓冲区
1)缓冲区的出现时为了提高流的操作效率而出现的.
2)需要被提高效率的流作为参数传递给缓冲区的构造函数
3)在缓冲区中封装了一个数组,存入数据后一次取出
3.输入字节流InputStream
定义和结构说明:
从输入字节流的继承图可以看出:InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
ObjectInputStream 和所有FilterInputStream的子类都是装饰流(装饰器模式的主角)。意思是FileInputStream类可以通过一个String路径名创建一个对象,FileInputStream(String name)。
DataInputStream必须装饰一个类才能返回一个对象,DataInputStream(InputStream in)。
public static void main(String[] args) throws IOException {
File f=new File("aaa.txt"); //定位文件位置
InputStream in=new FileInputStream(f); //创建字节输入流连接到文件
byte[] b=new byte[1024]; //定义一个数组,用来存放读入的数据 byte数组的大小也可以根据文件大小来定 (int)f.length()
int count =0;
int temp=0;
while((temp=in.read())!=(-1)){ //in.read()是逐字节读的。当读到文件末尾时候返回-1
b[count++]=(byte)temp; //将读到的字节存储到byte数组中
}
in.close(); //关闭流
System.out.println(new String(b)); //打印读取到的字节
}
注意:当读到文件末尾的时候会返回-1.正常情况下是不会返回-1的。
加入字节缓冲输入流,提高了读取效率
public static void main(String[] args) throws IOException {
File f=new File("aaa.txt"); //定位文件位置
InputStream in=new FileInputStream(f); //创建字节输入流连接到文件
BufferedInputStream bis=new BufferedInputStream(in); //创建缓冲字节流
byte[] b=new byte[1024]; //定义一个数组,用来存放读入的数据 byte数组的大小也可以根据文件大小来定 (int)f.length()
int count =0;
int temp=0;
bis.read();
while((temp=bis.read())!=(-1)){ //in.read()是逐字节读的。当读到文件末尾时候返回-1
b[count++]=(byte)temp; //将读到的字节存储到byte数组中
}
bis.close(); //关闭缓冲字节流
in.close(); //关闭流
System.out.println(new String(b)); //打印读取到的字节
}
4.输出字节流OutputStream
定义和结构说明:
IO 中输出字节流的继承图可见上图,可以看出:OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。
PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream的子类都是装饰流。具体例子跟InputStream是对应的。
public static void main(String[] args) throws IOException {
File f = new File("aaa.txt"); // 定位文件位置
OutputStream out = new FileOutputStream(f); // 创建字节输出流连接到文件
String str = "hhhhhhh";
byte[] b = str.getBytes(); //讲数据存入byte数组
out.write(b); //写数据
out.close(); //关闭流
}
加入字节缓冲输入流,提高了读取效率
public static void main(String[] args) throws IOException {
File f = new File("aaa.txt"); // 定位文件位置
OutputStream out = new FileOutputStream(f); // 创建字节输出流连接到文件
BufferedOutputStream bos=new BufferedOutputStream(out);
String str = "hhhhhhh";
byte[] b = str.getBytes(); //讲数据存入byte数组
bos.write(b); //写数据
bos.close(); //关闭缓冲流
out.close(); //关闭流
}
5.几个特殊的输入流类分析
LineNumberInputStream
主要完成从流中读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始中有这样一个行号。在输出部分没有对应的部分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行号,看起来也是可以的。好像更不入流了。
PushbackInputStream
其功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。
StringBufferInputStream
已经被Deprecated,本身就不应该出现在InputStream部分,主要因为String 应该属于字符流的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。
SequenceInputStream
可以认为是一个工具类,将两个或者多个输入流当成一个输入流依次读取。完全可以从IO 包中去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。
三、字符流
1.字符输入流Reader
定义和说明:
在上面的继承关系图中可以看出:Reader 是所有的输入字符流的父类,它是一个抽象类。
CharReader、StringReader是两种基本的介质流,它们分别将Char 数组、String中读取数据。
PipedReader 是从与其它线程共用的管道中读取数据。
BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。
public static void main(String[] args) throws IOException {
File f = new File("aaa.txt"); // 定位文件位置
char[] ch = new char[100]; //定义一个数组,用来存放读入的数据
Reader read = new FileReader(f); //创建字符输入流连接到文件
int count = read.read(ch); //读操作
read.close(); //关闭流
System.out.println("读入的长度为:" + count);
System.out.println("内容为" + new String(ch, 0, count));
}
加入缓冲流 提高效率。
public static void main(String[] args) throws IOException {
File f = new File("aaa.txt"); // 定位文件位置
char[] ch = new char[100]; //定义一个数组,用来存放读入的数据
Reader read = new FileReader(f); //创建字符输入流连接到文件
BufferedReader bfr=new BufferedReader(read); //创建缓冲流
int count = bfr.read(ch); //读操作
bfr.close(); //关闭缓冲流
read.close(); //关闭流
System.out.println("读入的长度为:" + count);
System.out.println("内容为" + new String(ch, 0, count));
}
2.字符输出流Writer
定义和说明:
在上面的关系图中可以看出:Writer 是所有的输出字符流的父类,它是一个抽象类。
CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。
PipedWriter 是向与其它线程共用的管道中写入数据,
BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似。
public static void main(String[] args) throws IOException {
File f=new File("aaa.txt"); // 定位文件位置
Writer out =new FileWriter(f); //创建字符输出流连接到文件
String str="哈哈哈哈哈哈";
out.write(str); //写操作
out.close(); //关闭流
}
加入缓冲流 提高效率。
public static void main(String[] args) throws IOException {
File f=new File("aaa.txt"); // 定位文件位置
Writer out =new FileWriter(f); //创建字符输出流连接到文件
BufferedWriter bfw =new BufferedWriter(out); //创建缓冲流
String str="哈哈哈哈哈哈";
bfw.write(str); //写操作
bfw.close(); //关闭缓冲流
out.close(); //关闭流
}
四、字符流与字节流转换
转换流的特点:
(1)其是字符流和字节流之间的桥梁
(2)可对读取到的字节数据经过指定编码转换成字符
(3)可对读取到的字符数据经过指定编码转换成字节
何时使用转换流?
当字节和字符之间有转换动作时;
流操作的数据需要编码或解码时。
具体的对象体现:
InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。
/**
* 将字节输出流转化为字符输出流
* */
public static void main(String[] args) throws IOException {
File file=new File("aaa.txt");
Writer out=new OutputStreamWriter(new FileOutputStream(file));
out.write("hello");
out.close();
}
/**
* 将字节输入流变为字符输入流
* */ public static void main(String[] args) throws IOException {
File file=new File("aaa.txt");
Reader read=new InputStreamReader(new FileInputStream(file));
char[] b=new char[100];
int len=read.read(b);
System.out.println(new String(b,0,len));
read.close();
}
IO流输入 输出流 字符字节流的更多相关文章
- IO流输入输出流,字符字节流
一.流 1.流的概念 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作. ...
- Java中的IO流之输出流|乐字节
大家好,乐字节小乐又来了.上一篇给大家带来的是:Java中的IO流之输入流|乐字节,本文将继续讲述IO流之输出流. 一.输出流 1.抽象类:OutputStream 和 Writer Output ...
- Java基础-IO流对象之字符缓冲流(BufferedWriter与BufferedReader)
Java基础-IO流对象之字符缓冲流(BufferedWriter与BufferedReader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.字符缓冲流 字符缓冲流根据流的 ...
- Java基础-IO流对象之字符类(FileWrite与FileReader)
Java基础-IO流对象之字符类(FileWrite与FileReader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常见编码简介 1>ASCII 我们知道计算机是 ...
- Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律
第一讲 IO概述 概述 1.IO流:即InputOutput的缩写. 2.特点: 1)IO流用来处理设备间的数据传输. 2)Java对数据的操作是通过流的方式. 3)Java用于操作流的对象都 ...
- IO流(File类,IO流的分类,字节流和字符流,转换流,缓冲流,对象序列化)
1.File类 File类可以在程序中 操作文件和目录.File类是通过建立File类对象,在调用File类的对象来进行相关操作的. 示例: public class Demo01 { public ...
- 十八、Java基础--------IO流体系以及字符流
在上一章节中详细介绍集合框架的相关知识,在接下来的几篇文章中将讲述Java中另一个及其重要的知识——IO流,本文主要是讲述IO流的一些基本概念以及字符流的相关应用. IO流 介绍IO流之前先介绍一下什 ...
- IO流(3)—字节流
IO体系: 抽象基类----节点流(文件流) InputStream--FileInputStream(字节流) OutputStream--FileOutputSteam(字节流) Reader - ...
- java基础44 IO流技术(输出字节流/缓冲输出字节流)和异常处理
一.输出字节流 输出字节流的体系: -------| OutputStream:所有输出字节流的基类(抽象类) ----------| FileOutputStream:向文件输出数据的输出字节流(把 ...
随机推荐
- [HDOJ2572]终曲
Problem Description 最后的挑战终于到了!站在yifenfei和MM面前的只剩下邪恶的大魔王lemon一人了!战胜他,yifenfei就能顺利救出MM.Yifenfei和魔王lemo ...
- ios8指纹识别
简介 苹果从iPhone5S开始,具有指纹识别技术,从iOS8.0之后苹果允许第三方 App 使用 Touch ID进行身份验证.指纹识别Touch ID提供3+2共5次指纹识别机会(3次识别失败后, ...
- Gradle之恋-命令行详解
虽然很多童鞋都必须要用IDE,但有些命令是IDE很难表现出来的,还是命令行返璞归真.本文就带你来剖析Gradle的命令行. 本文不包括试验性(incubating)的选项,如--configure-o ...
- 关于xml中有特珠字符而导致XmlDocument无法Load的处理
这是个小事故导致的... 我们线上有个节目里名称里(`F`H9)MSTJXCX0B3J69,虽然我们看到是(`F`H9)MSTJXCX0B3J69,但百思不得其解,发现每次在XmlDocument.L ...
- 分享一些自己写的前端库,并骗骗 star(库都是在实际项目中大量运用过的)
最近一两年在一些项目上,通过实际需求出发,编写了一些库在项目中使用,现在将这些项目都稍微整理了一下开源了出来,也许也有刚好能够你也用得上的,顺便也骗一下star.均在项目的README中加了相关的说明 ...
- 关于统一资源标志符URL的理解
URL由三部分构成 A:B:C A:URL使用的领域 B:在此领域的类型名称 C:标识资源的具体位置 C可以是一个绝对路径,也可以是端口号加上资源名称,总之是可以唯一标示资源的标识 例: 在网址中 S ...
- 图文:eclipse中SVN分支合并到主干
在项目开发中,需要添加一些新的功能,但是又不想影响到其他开发人员的项目进度,所以决定使用SVN分支进行开发,分支开发完毕后再合并到主干.本文介绍如何在eclipse中合并分支到主干. 1. 要想将分支 ...
- github多用户git push错误remote: Permission to user1/z.git denied to user2
背景:同一台电脑的public key同时添加到了github的两个账户,导致user1的仓库没法正常提交. 解决办法:为两个账户分别配置ssh key,配置~/.ssh/config文件(windo ...
- rgba兼容性处理
根据caniuse(http://caniuse.com/#search=rgba),rgba兼容性为IE9以及以上浏览器. 实例代码: <!doctype html> <html ...
- 解决ecshop进入后台服务器出现500的问题
ecshop安装完成以后,前台页面打开正常,但是后台页面大家会出现500错误,看了很多的论坛和网站,删除过top.htm里面的JS代码的,.htaccess文件的修改的,都没有解决,后来找到原因, 原 ...