I/O

I/O

文件对象

文件和文件夹都是用File代表

// 创建一个文件对象
String path = "..\java中期\IO\a.txt";
File file = new File(path);

什么是流

什么是流(Stream),流就是一系列的数据

文件输入流

FileInputStream fileInputStream = new FileInputStream(file);

字节流

编码

所有的数据存放在计算机中都是以数字的形式存放的。 所以字母就需要转换为数字才能够存放

比如A就对应的数字65,a对应的数字97. 不同的字母和符号对应不同的数字,就是一张码表。

就是编码的过程。

字节流是由字节组成的,所有的 InputStreamOutputStream 的子类都是,主要用在处理二进制数据

字符流

字符流是由字符组成的. 实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的encode来处理,也就是要进行字符集的转化。在从字节流转化为字符流时,实际上就是byte[]转化为String时,public String(byte bytes[], String charsetName)有一个关键的参数字符集编码

字符输入输出流

Reader字符输入流

Writer字符输出流

专门用于字符的形式读取和写入数据

// FileReader是Reader实现类,FileWriter是Writer的实现类
FileReader fr = new FileReader(f));
FileWriter fr = new FileWriter(f)

encode和decode的区别

在运行的时候,有时候会报编码错误,本文就来研究一下这个问题。

为什么会出现乱码呢?因为在文件存的时候格式和读取时候格式不一致就会乱码了。

字符串在java内部的表示是unicode编码,也可以说现在的内存是unicode编码格式,硬盘是utf-8。平常的数据操

作都是先把数据读取到内存中,所以内存中都是unicode编码格式。所以我们平常在做编码转换时候,通常用

unicode作为中间编码。先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码

格式。

decode的作用是将二进制数据解码unicode编码,如str1.decode('utf-8'),表示将utf-8的编码字符串解码成

unicode编码。

简单的来说:decode就是把二进制数据(bytes)转化成人看的懂得英文或者汉字(decode用的比较多)

encode的作用是将unicode编码的字符串编码成二进制数据,如str2.encode('utf-8'),表示将unicode编码的字符串

编码成utf-8

关闭流的方式

所有的流,无论是输入流还是输出流,使用完毕之后,都应该关闭。 如果不关闭,会产生对资源占用的浪费。 当

量比较大的时候,会影响到业务的正常开展。

在try中关闭(×

在try的作用域里关闭文件输入流,在前面的示例中都是使用这种方式,这样做有一个弊端;

如果文件不存在,或者读取的时候出现问题而抛出异常,那么就不会执行这一行关闭流的代码,存在巨大的资源占

用隐患。 不推荐使用

在finally中关闭 (

这是标准的关闭流的方式

  1. 首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally.
  2. 在finally关闭之前,要先判断该引用是否为空
  3. 关闭的时候,需要再一次进行try catch处理

这是标准的严谨的关闭流的方式,但是看上去很繁琐,所以写不重要的或者测试代码的时候,都会采用上面的有隐患try的方式,因为不麻烦~

中文乱码问题

常见的编码

ASCII码

img

0~31 非打印控制字符,32空格,48~59是阿拉伯数字,65 ~ 90大写字母,97~122是小写字母

GB2313

收录了6763个汉字

GBK

GBK全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification

Unicode

  • UTF-8 以字节为单位编码,汉字3字节,ASCII内字符1字节
  • UTF-16 以16位无符号整数为单位编码, 使用 2 个或者 4 个字节来存储,长度既固定又可变
  • UTF-32 以32位无符号整数为单位编码,都是4字节

乱码

假如使用UTF-8IDE环境打开GBK源码,解码时中文注释就会乱码

缓存流

BufferedInputStream作用

A BufferedInputStream为另一个输入流添加了功能,即缓冲输入并支持markreset方法的功能。 创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。 mark操作会记住输入流中的一个点,并且reset操作会导致从最近的mark操作读取的所有字节在从包含的输入流中取出新字节之前重新读取。

java.io下所有缓存流

Class 描述
BufferedInputStream 缓冲输入流
BufferedOutputStream] 缓冲输出流
BufferedReader 缓冲字符输入流
BufferedWriter 缓冲字符输出流

缓存区的定义

接收输入流,给到输出流

byte[] buffer = new byte[1024];
int len = -1;
while((len = <输入流>.read(buffer))!=-1){
     <输出流>.write(buffer);
};

数据流

DataInputStream 数据输入流
DataOutputStream 数据输出流

通过DataOutputStream 将特定格式数据写入文件,读取DataOutputStream 要按写入顺序读取。

//1.写入
File file = new File(path);
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);

dos.writeBoolean(true);
dos.writeBoolean(false);
dos.writeFloat((float) 1.235);
//2.读取
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);

boolean b = dis.readBoolean();
boolean b2 = dis.readBoolean();
float v = dis.readFloat();

对象流

对象流指的是可以直接把一个对象以流的形式传输给其他的介质,比如硬盘

一个对象以流的形式进行传输,叫做序列化。 该对象所对应的类,必须是实现Serializable接口

//Hero类的创建
public class Hero implements Serializable {
    //表示这个类当前的版本,如果有了变化,比如新设计了属性,就应该修改这个版本号
    private static final long serialVersionUID = 1L;
    public String name;
    public float hp;
 
}
//1.创建一个Hero garen
Hero h = new Hero();
h.name = "garen";
h.hp = 616;

//2.准备一个文件用于保存该对象
File f =new File("d:/garen.lol");

//3.创建输入输出流
//创建对象输出流
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos =new ObjectOutputStream(fos);
//创建对象输入流              
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois =new ObjectInputStream(fis);

//4.写入、读取
oos.writeObject(h);
Hero h2 = (Hero) ois.readObject();
System.out.println(h2.name);
System.out.println(h2.hp);
//5.释放资源

原文地址:https://www.cnblogs.com/sweetorangezzz/p/12902181.html