JAVA文件操作&IO流(二)

InputStream字节输入流

InputStrean

InputStream 就是Java 标准库提供的最基本的输入流。它位于java.io这个包里。InputStream 不是一个接口,而是一个抽象类,它是所有输入流的超类。

InputStream :字节输入流,进行字节内容的读取

FileInputStream 子类 :读取本地磁盘文件

读取方法1:

每次调用read()方法,读取到1个字节,读取至末尾返回-1

JAVA文件操作&IO流(二)_第1张图片

读取方法2:批量读取

定义一个数组保存每次读取的结果

JAVA文件操作&IO流(二)_第2张图片

缓冲读取

利用缓冲区一次性读取多个字节效率会提高

BufferedInputStream

BufferedInputStream 是缓冲输入流。它继承于FilerInputStream。BufferedInputStream的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持“mark()标记”和“reset()重置方法”。

BufferedInputStream 本身不具备读取的功能

BufferedInputStream 本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当我们通过read()读取输入流的数据时,BufferedInputStream会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完后,输入流会再次填充数据缓冲区;如此反复,直到读完。

JAVA文件操作&IO流(二)_第3张图片

OutputStream字节输出流

OutputStream 是Java标准库提供的用于写入操作的基础输入流。和InputStream 类似,OutputStream也是抽象类,它是所有输出流的超类。

BufferedOutputStream 缓冲输出流

BufferedOutputStream 和BufferedInputStream相似都是建立缓冲区。

JAVA文件操作&IO流(二)_第4张图片

BufferedOutputStream 的基本使用步骤:

1.创建FileOutputStream(字节输出流)对象,构造方法中绑定要输出的目标文件对象

2.创建BufferedOutputStream 对象,构造方法中传递FileOutputStream对象,提高FileOutputStream的写入效率

3.使用BufferedOutputStream 对象中的方法write() 方法,把数据写入到内部缓冲区中

4.使用BufferedOutputStream 对象中的flush()方法,把内部缓冲区的数据,刷新到文件中

5.使用BufferedOutputStream 对象中的close()方法,释放资源

JAVA文件操作&IO流(二)_第5张图片

Decorator 装饰器模式

装饰器模式概念

如果我们要给 FileInputStream 添加缓冲功能,则可以从 FileInputStream 派生一个子类 BufferedFileInputStream :

public class BufferedFileInputStream extends FileInputSream{ }

如果要给 FileInputStream 添加计算签名的功能,类似的,也可以从 FileInputStream 派生一个子类 DigestFileInputStream :

public class DigestFileInputStream extends FileInputStream{ }

如果要给 FileInputStream 添加加密/解密功能,还是可以从 FileInputStream 派生一个子类 CipherFileInputStream :

public class CipherFileInputStream extends FileInputStream{ }

如果要给 FileInputStream 添加缓冲和签名的功能,那么我们还需要派生子类 BufferedDigestFileInputStream 。如果要给 FileInputStream 添加缓冲和加解密的功能, 则需要派生 BufferedCipherFileInputStream 。

我们发现,给 FileInputStream 添加3种功能,至少需要3个子类。这3种功能的组合,又需要更多的子类,于是就有了装饰器

JAVA文件操作&IO流(二)_第6张图片

JAVA文件操作&IO流(二)_第7张图片

读取classpath资源文件

把资源存储在 classpath 中可以避免文件路径依赖;

Class 对象的 getResourceAsStream() 可以从 classpath 中读取指定资源;

根据 classpath 读取资源时,需要检查返回的 InputStream 是否为 null 。

public static void main(String[] args){
	//读取classpath下的properties文件
	try(InputStream in = Demo03.class.getResourceAsStream("/config.properties")){
		Properties prop = new Properties();
		prop.load(in);//通过properties对象加载*.properties文件
		
		System.out.println("key秘钥"+prop.getProperty("key","0000000000"));
	}catch(IOException e){
		e.printStackTrace();
	}
}

操作Zip压缩文件

概述

ZipInputStream 是一种 FilterInputStream ,它可以直接读取 zip 包的内容:
I n p u t S t r e a m ∣ F i l t e r I n p u t S t r e a m ∣ I n f l a t e r I n p u t S t r e a m ∣ Z i p I n p u t S t r e a m ∣ J a r I n p u t S t r e a m InputStream ^ | FilterInputStream ^ | InflaterInputStream ^ | ZipInputStream ^ | JarInputStream InputStreamFilterInputStreamInflaterInputStreamZipInputStreamJarInputStream

读取Zip包

ZipInputStream 的基本用法: 首先要创建一个 ZipInputStream ,通常是传入一个 FileInputStream 作为数据 源,然后,循环调用 getNextEntry() ,直到返回 null ,表示 zip 流结束。 一个 ZipEntry 表示一个压缩文件或目录,如果是压缩文件,我们就用 read() 方法不断读取,直到返回 -1

JAVA文件操作&IO流(二)_第8张图片

JAVA文件操作&IO流(二)_第9张图片

写入Zip包

ZipOutputStream 是一种 FilterOutputStream ,它可以直接写入内容到zip包。我们要先创建一个 ZipOutputStream ,通常是包装一个 FileOutputStream ,然后,每写入一个文件前,先调用 putNextEntry() ,然后用 write() 写入 byte[] 数据,写入完毕后调用 closeEntry() 结束这个文件的 打包

JAVA文件操作&IO流(二)_第10张图片

小结

ZipInputStream 可以读取 zip 格式的流, ZipOutputStream 可以把多份 数据写入 zip 包;配合 FileInputStream 和 FileOutputStream 就可以读写zip文件

Serializable序列化

概述

序列化是指把一个 Java 对象变成二进制内容,本质上就是一个 byte[] 数组。 为什么要把Java对象序列化呢?因为序列化后可以把 byte[] 保存到文件中,或 者把 byte[] 通过网络远程传输。这样,就相当于把 Java 对象存储到文件或者通过 网络传输出去了。有序列化,就有反序列化,即把一个二进制内容(也就是 byte[] 数组)变回 Java 对象。有了反序列化,保存到文件中的 byte[] 数组又可以“变回” Java对象,或者从网络上读取 byte[] 并把它“变回”Java对象。

序列化

把一个Java对象变为 byte[] 数组,需要使用 ObjectOutputStream 。它负责把一个Java对象写入一个字 节流。 ObjectOutputStream 既可以写入基本类型,如 int , boolean ,也可以写入 String (以UTF8编码),还可以写入实现了 Serializable 接口的 Object 。因为写入 Object 时需要大量的类型信 息,所以写入的内容很大。

import java.io.*;
import java.util.Arrays;

public class Main {
 	public static void main(String[] args) throws IOException {
 		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 		try (ObjectOutputStream output = new ObjectOutputStream(buffer)) {
 			// 写入int:
 			output.writeInt(12345);
 			// 写入String:
 			output.writeUTF("Hello");
 			// 写入Object:
 			output.writeObject(Double.valueOf(123.456));
 		}
 		System.out.println(Arrays.toString(buffer.toByteArray()));
 	}
}
反序列化

和 ObjectOutputStream 相反, ObjectInputStream 负责从一个字节流读取Java对象:

try (ObjectInputStream input = new ObjectInputStream(...)) {
 	int n = input.readInt();
 	String s = input.readUTF();
 	Double d = (Double) input.readObject();
}
小结

可序列化的Java对象必须实现 java.io.Serializable 接口,类似 Serializable 这样的空接口被称为“标记接口”( Marker Interface );

反序列化时不调用构造方法,可设置 serialVersionUID 作为版本号(非必需);

Java的序列化机制仅适用于Java,如果需要与其它语言交换数据,必须使用通用 的序列化方法,例如 JSON 。

reader读取文本文件和writer写入文本文件

JAVA文件操作&IO流(二)_第11张图片

JAVA文件操作&IO流(二)_第12张图片

转换流(将字节流转换为字符流)

通过InputStreamReader转换流将字节流转换为Reader字符流

JAVA文件操作&IO流(二)_第13张图片

作为版本号(非必需);

Java的序列化机制仅适用于Java,如果需要与其它语言交换数据,必须使用通用 的序列化方法,例如 JSON 。

reader读取文本文件和writer写入文本文件

[外链图片转存中…(img-orfLkxAu-1706093748833)]

[外链图片转存中…(img-hWWeOS3E-1706093748833)]

转换流(将字节流转换为字符流)

通过InputStreamReader转换流将字节流转换为Reader字符流

[外链图片转存中…(img-5pozmc1u-1706093748833)]

你可能感兴趣的:(java,java,python,开发语言)