流与文件

java 流定义:可以从中读入一个字节序列的对象称为 输入流;可以向其写入字节序列的是 输出流
主要有2种基类:InputStream 、OutputStreamReader、WriterInputStream 、OutputStream处理单字节的字符;Reader、Writer处理 两字节的Unicode码元。
InputStream 的read方法读入一个字节,OutputStream的write方法写入一个字节;read 和writer方法执行的时候线程都会阻塞。
注意 流打开后都需要close;OutputStream最后必须调用flush函数,将所有缓冲数据发送到目的地

流家族

流家族可以通过这两张图分成2大类
在这里插入图片描述
在这里插入图片描述

组合流过滤器

假设有这样一个场景:我们需要从一个数据文件 中读取数据。
首先我们确定最外层的类:因为要读取数值,所以选择DataInputStream;我们需要从文件中获得数据流,所以里面使用FileInputStream 从文件中获得输入流;为了提高效率,我们需要增加一个缓冲区,所以中间加一个BufferedInputStream;所以最终的代码就是

DataInputStream din = new DataInputStream(
	new BufferedInputStream(
		new FileInputStream("employee.data")));

文本输入输出

文本输出使用的类是PrintWriter;使用:

PrintWriter pw= new PrintWriter("test.txt");
//或者
PrintWriter pw= new PrintWriter(new FileWriter("test.txt"));
pw.print("test")
pw.print(' ')
pw.println()

PrintWriter和打印到终端的System.out类似;其他api可以查文档;注意如果没有设置自动println不会flush;

文本读入有两种方式:
通过BufferedReader和Scanner;感觉没啥好说的,很简单。

BufferedReader bf= new BufferedReader(new InputStreamReader(new FileInputStream("test.txt"),"UTF-8"))

对象序列化

java的序列化主要是通过实现serializable接口实现的但是,其实我们可以修改默认的序列化方式。

修改默认的序列化机制

对于序列化的对象,我们可以将他的域标记成transient,这样的对象在序列化的过程中会被跳过;
我们可以通过复写readObject和writeObject类,向默认的读写行为添加验证或者任何其他想要的行为

private void writeObject(ObjectInputStream in) throw IOException,ClassNotFoundException
private void readObject(ObjectOutputStream out) throw IOException

对象还可以实现Externalizable 接口,需要实现它的两个方法:

private void writeExternal(ObjectInputStream in) throw IOException,ClassNotFoundException
private void readExternal(ObjectOutputStream out) throw IOException

需要注意的是,这两个方法和readObject和writeObject不一样的是,这两个方法对包括超类在内的对象数据恢复和存储负全责,而序列化就是在流中仅仅记录所属对象所属的类。

单例和类型安全的枚举序列化

假设需要序列化这样的枚举

public class Orientation{
public static final Orientation HORIZONTAL = new Orientation(1);
public static final Orientation VERTICAL = new Orientation(2);
private int value;
private Orientation(int v){
value = v;
}

}

可以使用==来判断是不是相等;但是序列化后会变成一个新的对象,所以这样的==是不相等的;那么我们需要定义一种readResolve的机制。

protected Object readResolve() throws ObjectStreamException{
if(value ==1) return Orientation.HORIZONTAL;
if(value == 2) return Orientation.VERTICAL;
return null;
}

对象序列化版本管理

首先必须提供一个静态的serialVersionUID 变量,就不需要再计算其指纹,这样就可以读取不同版本的类对象。
对象流将尽力 将流对象转换成这个类当前的版本,对象流只会 考虑非瞬时和非静态的数据域
如果这两部分数据域之间名字匹配而类型不匹配,那么对 象流不会尝试将一种类型转换成另一种类型,因为这两个对象不兼容;如果流中的对象具有 在当前版本中所没有的数据域,那么对象流会忽略这些额外的数据;如果当前版本具有在流化对象中所没有的数据域,那么这些新添加的域将被设置成它们的默认值(如果是对象则是 null,如果是数字则为 0,如果是 boolean 值则是 false)。

序列化用于克隆对象

其做法很简单:直接将对象序列化到输出流中,然后将其读回。这样产生 的新对象是对现有对象的一个深拷贝(deep copy)。但是它通常会比显式地构建新对象并复制或克 隆数据域的克隆方法慢得多。

Files 和Path

简单说就是很方便的工具类,可以用的时候自己再看;不需要什么文件操作都通过file来做

文件内存映射

定义:利用虚拟内存将一个文件或者文件的一部分映射到虚拟内存中,然后就可以将这个文件当做数组一样的访问。
文件内存映射关键的一个类是FIleChannel,它使我们能够访问内存映射,文件加锁机制以及文件间数据快速传递等操作系统特性。

FileChannel类可以得到一个ByteBuffer对象,这样就可以很好地操作文件了

在对文件的读写时。可以通过FileChannel类实现文件的加锁。
一般实现方式

try(FileLock lock = channel.lock()){
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值