IO流分类:java.io包
流的分类
- 流向来分
- 输入流:只能从硬盘或文件读取数据,不能写入数据
- 输出流:只能向文件硬盘写入数据,不能读取数据
- 操作单元来分
- 字节流:
- InputStream (抽象方法)
- FileInputStream
- BufferedInputStream
- OutputStream(抽象方法)
- FileOutputStream
- BufferedOutputStream
- InputStream (抽象方法)
- 字符流:
- Reader (抽象方法)
- FileReader
- BufferedReader
- Writer(抽象方法)
- FileWriter
- BufferedWriter
- Reader (抽象方法)
- 字节流:
- 流的角色来分
- 节点流(低级流):从/向一个特定的IO设备读/写数据的流
- 处理流:对一个已经存在的流进行连接或者封装,通过封装后的流来实现数据读写功能
字节流操作是万能的,但是字符流却不是万能的
字符流 = 字节流+编码表
import java.io.FileInputStream;
import java.io.IOException;
/**
* java IO流
* java把不同的输入/输出源抽象表述为“流” 通过流的方式允许java程序使用相同的方式来
* 访问不同的输入/输出源。
* java所有传统的流类型都放在java.io包中,用于实现输入输出流
* <p>
* 流的分类
* 1,输入流:只能从中读取数据,不能向其中写入数据
* 2,输出流:只能向其写入数据,而不能从中读取数据
* <p>
* 输入流基类(抽象类): inputStream ,Reader。
* 输出流基类(抽象类):outputStream,Wirter。
* <p>
* 1,字节流:数据单元8字节
* 2,字符流:数据单元16字符
* <p>
* 字节流基类:inputStream , outputStream.
* 字符流基类:Reader, Wirter.
* <p>
* 1,节点流(低级流):可以从或者向一个特定的IO设备读写的流
* 2,字符流(高级流):用于一个已存在的流进行连接或者封装来实现数据读写功能
* <p>
* 流的概念模型:水滴
* 处理流主要功能:
* 性能的提高:主要以增加缓冲的方式来提高输入/输出的效率
* 操作的便捷:处理流可能提供了一系列便捷的方法来一次输出输入大批的内容,而不是输入/输出一个或者多个水滴。
* <p>
* 方法API
* <p>
* 抽象不能创建实例但是有输入流FileInputStream和FileReader
* 输出流FileOutputStream和FileWirter
*
*
*
*/
public class FileInputStreamTest {
public static void main(String[] args) throws IOException {
//创建字节输入流 字节问题
FileInputStream fis = new FileInputStream("F:\\day9\\protects最新\\src\\banban\\study13\\IO\\IO\\FileInputStreamTest.java");
//创建一个长度为1024的“竹筒”
byte[] bbuf = new byte[1024];
//用于保存实际读取的 字节数
int hasRead = 0;
//使用循环来重复取水过程
while ((hasRead=fis.read(bbuf))>0){
//取出竹筒中的水滴(字节),将字节数组转换成字符串输入
System.out.print(new String(bbuf,0,hasRead));
}
// hasRead = fis.read(bbuf);
// System.out.print(new String(bbuf,0,hasRead));
System.out.println(hasRead);
//关闭文件输入流
fis.close();
}
}
- 操作过程:
- 创建字节输出/输出流对象
- 调用write()/read()方法
- 释放资源.
- 使用try。。。catch。。块
- 因为IO流异常的原因,我们尽量使用try。。。catch。。块来进行IO流程序的设计。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* @ClassName CopyTest
* @Author zhang-peng-zhan
* @Date 2018/11/7 16:25
*/
public class CopyTest {
//复制文本文件
//将锦瑟:F:\day9\protects最新\锦瑟.txt
//复制到:F:\day9\protects\锦瑟复制版.txt(并起名为锦瑟复制版.txt)
public static void main(String[] args) {
try(FileReader fileReader = new FileReader("F:\\day9\\protects最新\\锦瑟.txt");
FileWriter fileWriter = new FileWriter("F:\\day9\\protects最新\\锦瑟复制版.txt")
) // 小括号用来管理释放资源,当try catch语句结束 小括号里的资源会被jvm释放掉
// 前提是这些可关闭的资源必须实现了java.lang.Aotocloseable接口
//省略了使用close方法释放资源这一步。
{
char[] chars = new char[32];
int hasRead = 0;
while ((hasRead = fileReader.read(chars))>0){
fileWriter.write(chars,0,hasRead);
}
}catch (IOException e){
e.printStackTrace();
}
}
}
字节字符缓冲区流
-
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流
-
从字符/字符输入/输出流中读取/写文本,缓冲各个字节或者字符,从而实现字节、字符、数组和行的高效读取/写。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。 -
字节缓冲输出流
- BufferedOutputStream
-
字节缓冲输入流
- BufferedInputStream
-
字符缓冲输出流
- BufferedWriter
-
字符缓冲输入流
- BufferedReader
BufferedOutputStream:字节缓冲输出流
- 构造方法可以设置缓冲区大小
- 构造方法传的对象还是一个outputstream对象,这是因为缓冲流仅仅是提供了一个缓冲区,为效率设计,而真正的读写操作还得靠基本的流实现。
public class BufferedOutputStreamTest {
public static void main(String[] args) throws IOException {
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(new FileOutputStream("a.txt"));
bufferedOutputStream.write("hello".getBytes());
bufferedOutputStream.close();
}
}
BufferedinputStream:字节缓冲输入流
- 同上面的字节缓冲输出流
public class BufferedinputStreamTest {
public static void main(String[] args) throws IOException {
BufferedInputStream bufferedInputStream =
new BufferedInputStream(new FileInputStream("a.txt")); //a文件内容hello
byte[] bytes = new byte[5];
int hasread;
hasread = bufferedInputStream.read(bytes);
System.out.println(new String(bytes,0,hasread));
}
}
字符缓冲流和字节缓冲流的用法一样,这里不做介绍了。
转换流:字节流数据转换为字符流数据
字节流使用广泛,字符流操作方便。在对文本文件进行操作时,我们习惯性使用更加方便的字符流,所以java提供了字节流到字符流的转换。
- OutputStreamWriter:字节输出流转字符输出流
- 默认编码(GBK)
- 构造方法可以指定编码
- InoutStreamReader:字节输入流转字符输入流
- 默认的编码(GBK)
- 构造方法可以指定编码
- 因为转换流名称太长,所以使用默认的子类FileWriter和FileReader来进行文本文件的操作。
字符流的由来:
- 因为一个中文汉字占两个字节,如果使用字节流操作,我们就需要对这个汉字进行拆分和合并,比较麻烦,java为了方便的操作中文就给我们提供了一个字符流,但是计算机现在操作的最小单位时字节,那么操作数据,本质还是对最小单位的操作,于是这个字符流底层还是使用的字节流,那么要使用字符流,就需要对这个中文汉字进行拆分和合并,那么按照的就是编码表进行拆分合并。
- 字符流=字节流+编码表
- 编码表:
- ASCLL
- GB2312
- GBK:简体中文字符集
- BIG5:繁体中文字符集
- UNICODE(usc-2,usc-4)
- UTF-8:8为UCS转换格式
规则:如果进行输出输入的内容是文本,则应该考虑使用字符流,如果输入输出的内容是二进制内容,则应该考虑使用字节流,这里通用缓冲流。
杂七杂八的流
数据输入和输出流:
- 数据输入流: DataInputStream
- 数据输出流: DataOutputStream
- 可以写基本数据类型,可以读取基本数据类型
内存操作流
- 操作字节数组
- ByteArrayOutputStream
- ByteArrayInputStream
- 此流关闭无效,所以无需关闭
- 操作字符数组
- CharArrayWrite
- CharArrayReader
- 操作字符串
- StringWriter
- StringReader
随机访问流:RandomAccessFile
- RandomAccessFile: 能读能写
- RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。支持对随机访问文件的读取和写入。
- RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针
打印流:PrintStream/PrintWriter
- 分类:
- PrintStream
- PrintWriter
- 特点:
- 只有写数据,没有读数据。只能操作目的地,不能操作数据源
- 可以操作任意类型数据
- 有自动刷新功能
- 该流可以直接操作文件对象
合并流: SequenceInputStream
- SequenceInputStream:把多个输入流数据写到一个输入流中
- 构造方法:
- SequenceInputStream(InputStream s1, InputStream s2) :通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
- SequenceInputStream(Enumeration<? extends InputStream> e) :通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
序列化流:ObjectOutputStream
- 此流操作的是java对象,但是想要使用这个流,
必须实现序列化接口:Serializable(标记接口) - ObjectOutputStream:将java对象写入OutputStream流中,可以使用ObjectOutputStream的方法实现读取,存储,传输。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
- ObjectinputStream:将流数据还原为对象。
- 注意:序列化对象时 要求此类实现 Serializable 序列化接口,Serializable 序列化接口 标记即可
Properties
- 持久的属性集,Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
- Properties与IO流的结合
- void load(Reader reader) : 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
- void store(Writer writer, String comments) :以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符
计算机在读文件存文件时候怎么识别是中文还是字符。
- 当使用文件流读文件存文件(字节流)
- 当遇到的是字符,读取的字节将会是一个整数。
- 当遇到的是中文(一个中文被看成两个字节),这时候读取的两个字节,第一个字节必是负数,第二个可能是正数,可能是负数。
- 以此,计算机来辨认读取和存取到的是字符还是中文。