2021-11-10

Java IO

基类:

InputStream

这个抽象类是所有表示字节输入流的类的超类。
需要定义 InputStream 子类的应用程序必须始终提供返回输入的下一个字节的方法。
也可以看看:BufferInputStream, ByteArrayInputStream, DataInputStream, FilterInputStream, read(), OutoutStream, PushbackInputStream;

public abstract class InputStream implements Closeable{
	// MAX_SKIP_BUFFER_SIZE 用于确定最大缓冲区大小
     // 跳过时使用。
	private static final int MAX_SKIP_BUFFER/-SIZE = 2048;

从输入流中读取下一个字节的数据。 值字节以 0255 范围内的 int 形式返回。如果由于已到达流末尾而没有可用字节,则返回值 -1。 此方法会阻塞,直到输入数据可用、检测到流结束或抛出异常为止。
子类必须提供此方法的实现。
返回:
数据的下一个字节,如果到达流的末尾,则为 -1。
抛出:
IOException – 如果发生 I/O 错误。
	public abstract int read() throws IOException;


从输入流中读取一定数量的字节并将它们存储到缓冲区数组 b 中。实际读取的字节数作为整数返回。此方法会阻塞,直到输入数据可用、检测到文件结尾或抛出异常。
如果 b 的长度为零,则不读取字节并返回 0;否则,将尝试读取至少一个字节。如果由于流位于文件末尾而没有可用字节,则返回值 -1;否则,至少读取一个字节并存入 b。
读取的第一个字节存储到元素 b[0] 中,下一个存储到 b[1] 中,依此类推。读取的字节数最多等于 b 的长度。令 k 为实际读取的字节数;这些字节将存储在元素 b[0] 到 b[k-1] 中,元素 b[k] 到 b[b.length-1] 不受影响。
InputStream 类的 read(b) 方法具有与以下相同的效果:
 读取(b, 0, b.length)
参数:
b – 读取数据的缓冲区。
返回:
读入缓冲区的总字节数,如果由于已到达流末尾而没有更多数据,则为 -1。
抛出:
IOException – 如果由于文件末尾以外的任何原因无法读取第一个字节,如果输入流已关闭,或者如果发生其他一些 I/O 错误。
NullPointerException – 如果 b 为空。
	public int read(byte b[]) throws IOException{
}
  
跳过并丢弃此输入流中的 n 字节数据。由于多种原因,skip 方法可能最终跳过一些较小数量的字节,可能是 0。这可能是由多种情况中的任何一种引起的;在跳过 n 个字节之前到达文件末尾只是一种可能性。返回实际跳过的字节数。如果 n 为负数,则 InputStream 类的跳过方法始终返回 0,并且不会跳过任何字节。子类可能会以不同的方式处理负值。
此类的skip 方法创建一个字节数组,然后重复读入其中,直到已读取n 个字节或已到达流的末尾。鼓励子类提供此方法的更有效实现。例如,实现可能取决于搜索的能力。
参数:
n – 要跳过的字节数。
返回:
实际跳过的字节数。
抛出:
IOException – 如果流不支持搜索,或者发生其他一些 I/O 错误。	
	public long skip(long n) throws IOException{
	}

返回可以从此输入流读取(或跳过)的字节数的估计值,而不会因下一次调用此输入流的方法而阻塞。下一次调用可能是同一个线程或另一个线程。单次读取或跳过这么多字节不会阻塞,但可能读取或跳过更少的字节。
请注意,虽然 InputStream 的某些实现会返回流中的总字节数,但许多不会。使用此方法的返回值来分配用于保存此流中所有数据的缓冲区永远是不正确的。
如果此输入流已通过调用 close() 方法关闭,则此方法的子类实现可能会选择抛出 IOExceptionInputStream 类的可用方法始终返回 0。
这个方法应该被子类覆盖。
返回:
估计可以从此输入流读取(或跳过)的字节数而不会阻塞,或者在到达输入流末尾时为 0。
抛出:
IOException – 如果发生 I/O 错误。
	public int available() throws IOException{
	return 0;
	}

关闭此输入流并释放与该流关联的所有系统资源。
InputStream 的 close 方法什么也不做。
抛出:
IOException – 如果发生 I/O 错误。
	public void close() throws IOException{}


标记此输入流中的当前位置。 对 reset 方法的后续调用将此流重新定位在最后标记的位置,以便后续读取重新读取相同的字节。
readlimit 参数告诉此输入流允许在标记位置无效之前读取许多字节。
mark 的一般约定是,如果方法 markSupported 返回 true,则流以某种方式记住调用 mark 后读取的所有字节,并随时准备在调用方法 reset 时再次提供这些相同的字节。 但是,如果在调用 reset 之前从流中读取了超过 readlimit 个字节,则该流根本不需要记住任何数据。
标记关闭的流不应对流产生任何影响。
InputStream 的标记方法什么也不做。
参数:
readlimit – 在标记位置变为无效之前可以读取的最大字节数。
	public synchronized void mark(int readlimit){}


将此流重新定位到上次在此输入流上调用 mark 方法时的位置。
重置的总合约为:
如果方法 markSupported 返回 true,则:
如果自创建流后尚未调用方法标记,或者自上次调用标记以来从流中读取的字节数大于上次调用时标记的参数,则可能会抛出 IOException。
如果没有抛出这样的 IOException,那么流被重置为这样一种状态,即自最近一次调用 mark(或自文件开始,如果 mark 未被调用)以来读取的所有字节将重新提供给后续read 方法的调用者,后跟在调用 reset 时将成为下一个输入数据的任何字节。
如果方法 markSupported 返回 false,则:
对 reset 的调用可能会引发 IOException。
如果未抛出 IOException,则该流将重置为固定状态,该状态取决于输入流的特定类型及其创建方式。将提供给 read 方法的后续调用者的字节取决于输入流的特定类型。
InputStream 类的 reset 方法除了抛出 IOException 之外什么都不做。
抛出:
IOException – 如果此流尚未标记或标记已失效。
	public synchronized void reset() throws IOException{
	}


测试此输入流是否支持标记和重置方法。 是否支持标记和重置是特定输入流实例的不变属性。 InputStream 的 markSupported 方法返回 false。
返回:
如果此流实例支持标记和重置方法,则为 true; 否则为假。
	public boolean markSupported(){return false;} 
}

OutputStream

这个抽象类是所有表示字节输出流的类的超类。 输出流接受输出字节并将它们发送到某个接收器。
需要定义 OutputStream 子类的应用程序必须始终至少提供一种写入一个字节输出的方法。
也可以看看:
BufferedOutputStream, ByteArrayOutputStream,
DataOutputStream, FilterOutputStream, InputStream, write(int)

public abstract class OutputStream implements Closerable,Flushable{


将指定的字节写入此输出流。 write 的一般约定是将一个字节写入输出流。 要写入的字节是参数 b 的低 8 位。 b 的 24 个高位被忽略。
OutputStream 的子类必须为此方法提供实现。
参数:
b——字节。
抛出:
IOException – 如果发生 I/O 错误。 特别是,如果输出流已关闭,则可能会抛出 IOExceptionpublic abstract void write(int b) throws IOException;


将指定字节数组中的 b.length 个字节写入此输出流。 write(b) 的一般约定是它应该与调用 write(b, 0, b.length) 具有完全相同的效果。
参数:
b——数据。
抛出:
IOException – 如果发生 I/O 错误。
public void write(byte b[]) throws IOExcetion{
}


将指定字节数组中的 len 个字节从偏移量 off 开始写入此输出流。 write(b, off, len) 的一般约定是将数组 b 中的某些字节按顺序写入输出流; 元素 b[off] 是写入的第一个字节,b[off+len-1] 是此操作写入的最后一个字节。
OutputStream 的 write 方法对每个要写出的字节调用一个参数的 write 方法。 鼓励子类覆盖此方法并提供更有效的实现。
如果 b 为 null,则抛出 NullPointerException。
如果 off 为负数,或 len 为负数,或 off+len 大于数组 b 的长度,则抛出 IndexOutOfBoundsException。
参数:
b——数据。
off – 数据中的起始偏移量。
len – 要写入的字节数。
抛出:
IOException – 如果发生 I/O 错误。 特别是,如果输出流关闭,则会抛出 IOExceptionpublic void write(byte b[], int off, lnt len) throws IOException{
	}


刷新此输出流并强制写出任何缓冲的输出字节。 刷新的一般约定是调用它表明,如果先前写入的任何字节已被输出流的实现缓冲,则应立即将这些字节写入其预期目的地。
如果此流的预期目标是底层操作系统提供的抽象,例如文件,则刷新流仅保证先前写入流的字节会传递给操作系统进行写入; 它不保证它们确实被写入物理设备,例如磁盘驱动器。
OutputStream 的flush 方法什么也不做。
抛出:
IOException – 如果发生 I/O 错误。
	public void flush() throws IOException{}


关闭此输出流并释放与此流关联的任何系统资源。 close 的一般约定是它关闭输出流。 关闭的流无法执行输出操作,也无法重新打开。
OutputStream 的 close 方法什么也不做。
抛出:
IOException – 如果发生 I/O 错误。
	public vod close() throws IOException{}
}

Reader

用于读取字符流的抽象类。 子类必须实现的唯一方法是 read(char[], int, int) 和 close()。 然而,大多数子类会覆盖这里定义的一些方法,以提供更高的效率、附加功能或两者兼而有之。
也可以看看:
BufferedReader、LineNumberReader、CharArrayReader、InputStreamReader、FileReader、FilterReader、PushbackReader、PipedReader、StringReader、Writer

public abstract class Reader implements Readable,Closeable{
}

Writer

用于写入字符流的抽象类。 子类必须实现的唯一方法是 write(char[], int, int)、flush() 和 close()。 然而,大多数子类会覆盖这里定义的一些方法,以提供更高的效率、附加功能或两者兼而有之。
也可以看看:
Writer、BufferedWriter、CharArrayWriter、FilterWriter、OutputStreamWriter、FileWriter、PipedWriter、PrintWriter、StringWriter、Reader

public abstract class Writer implements Appendale, Closeable, Flushable{
}

子类

ObjectOutputStream

ObjectOutputStream 将 Java 对象的原始数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。对象的持久存储可以通过对流使用文件来实现。如果流是网络套接字流,则可以在另一个主机或另一个进程中重构对象。
只有支持 java.io.Serializable 接口的对象才能写入流。每个可序列化对象的类都被编码,包括类名和类的签名、对象字段和数组的值,以及从初始对象引用的任何其他对象的闭包。
writeObject 方法用于将对象写入流。任何对象,包括字符串和数组,都是用 writeObject 编写的。可以将多个对象或基元写入流。对象必须从对应的 ObjectInputstream 中以相同的类型和相同的顺序被读回。
还可以使用 DataOutput 中的适当方法将原始数据类型写入流。也可以使用 writeUTF 方法编写字符串。
对象的默认序列化机制写入对象的类、类签名以及所有非瞬态和非静态字段的值。对其他对象的引用(瞬态或静态字段除外)会导致这些对象也被写入。对单个对象的多个引用使用引用共享机制进行编码,以便对象图可以恢复到与原始对象相同的形状。
例如编写一个可以被 ObjectInputStream 中的例子读取的对象:
FileOutputStream fos = new FileOutputStream(“t.tmp”);
ObjectOutputStream oos = new ObjectOutputStream(fos);

    oos.writeInt(12345);
    oos.writeObject("今天");
    oos.writeObject(新日期());

    oos.close();

在序列化和反序列化过程中需要特殊处理的类必须实现具有以下确切签名的特殊方法:
private void readObject(java.io.ObjectInputStream 流)
抛出 IOException,ClassNotFoundException;
private void writeObject(java.io.ObjectOutputStream 流)
抛出 IOException
私有无效 readObjectNoData()
抛出 ObjectStreamException;

writeObject 方法负责为其特定类写入对象的状态,以便相应的 readObject 方法可以恢复它。该方法不需要关心属于对象的超类或子类的状态。通过使用 writeObject 方法或使用 DataOutput 支持的原始数据类型的方法将各个字段写入 ObjectOutputStream 来保存状态。
序列化不会写出任何未实现 java.io.Serializable 接口的对象的字段。不可序列化的对象的子类可以是可序列化的。在这种情况下,不可序列化的类必须有一个无参数构造函数以允许初始化其字段。在这种情况下,子类负责保存和恢复不可序列化类的状态。通常情况下,该类的字段是可访问的(公共的、包的或受保护的),或者存在可用于恢复状态的 get 和 set 方法。
可以通过实现抛出 NotSerializableException 的 writeObject 和 readObject 方法来防止对象的序列化。异常将被 ObjectOutputStream 捕获并中止序列化过程。
实现 Externalizable 接口允许对象完全控制对象序列化形式的内容和格式。调用 Externalizable 接口的方法 writeExternal 和 readExternal 来保存和恢复对象状态。当由类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法写入和读取自己的状态。对象负责处理发生的任何版本控制。
枚举常量的序列化方式与普通的可序列化或外部化对象不同。枚举常量的序列化形式仅由其名称组成;不传输常量的字段值。为了序列化一个枚举常量,ObjectOutputStream 写入由常量的 name 方法返回的字符串。与其他可序列化或可外部化对象一样,枚举常量可以作为随后出现在序列化流中的反向引用的目标。枚举常量序列化的过程无法自定义;在序列化期间,将忽略枚举类型定义的任何特定于类的 writeObject 和 writeReplace 方法。类似地,任何serialPersistentFields 或serialVersionUID 字段声明也将被忽略——所有枚举类型都有一个固定的0L 的serialVersionUID。
原始数据(不包括可序列化字段和可外部化数据)以块数据记录的形式写入 ObjectOutputStream。块数据记录由头和数据组成。块数据头由一个标记和跟在头后面的字节数组成。连续的原始数据写入合并为一个块数据记录。用于块数据记录的分块因子将为 1024 字节。每个块数据记录最多可填充 1024 个字节,或者在块数据模式终止时写入。对 ObjectOutputStream 方法 writeObject、defaultWriteObject 和 writeFields 的调用最初会终止任何现有的块数据记录。

public class ObjectOutputStream extends OutputStream implements ObjectOutput,ObjectStreamConstants{
}

ObjectInputStream

ObjectInputStream 反序列化之前使用 ObjectOutputStream 编写的原始数据和对象。
当分别与 FileOutputStream 和 FileInputStream 一起使用时,ObjectOutputStream 和 ObjectInputStream 可以为应用程序提供对象图的持久存储。 ObjectInputStream 用于恢复之前序列化的那些对象。其他用途包括使用套接字流在主机之间传递对象,或用于在远程通信系统中编组和解组参数和参数。
ObjectInputStream 确保从流创建的图中所有对象的类型与 Java 虚拟机中存在的类相匹配。使用标准机制根据需要加载类。
只能从流中读取支持 java.io.Serializable 或 java.io.Externalizable 接口的对象。
readObject 方法用于从流中读取对象。应该使用 Java 的安全转换来获得所需的类型。在 Java 中,字符串和数组是对象,在序列化过程中被视为对象。读取时,它们需要转换为预期的类型。
可以使用 DataInput 上的适当方法从流中读取原始数据类型。
对象的默认反序列化机制将每个字段的内容恢复为写入时的值和类型。反序列化过程会忽略声明为瞬态或静态的字段。对其他对象的引用会导致根据需要从流中读取这些对象。使用引用共享机制正确恢复对象图。反序列化时总是分配新对象,这样可以防止现有对象被覆盖。
读取一个对象类似于运行一个新对象的构造函数。为对象分配内存并初始化为零 (NULL)。为不可序列化的类调用无参数构造函数,然后从流中恢复可序列化类的字段,从最接近 java.lang.object 的可序列化类开始,并以对象的最具体的类结束。
例如,从 ObjectOutputStream 中的示例写入的流中读取:
FileInputStream fis = new FileInputStream(“t.tmp”);
ObjectInputStream ois = new ObjectInputStream(fis);

    int i = ois.readInt();
    今天的字符串 = (String) ois.readObject();
    日期 date = (Date) ois.readObject();

    ois.close();

类通过实现 java.io.Serializable 或 java.io.Externalizable 接口来控制它们的序列化方式。
实现 Serializable 接口允许对象序列化保存和恢复对象的整个状态,并允许类在写入流的时间和读取流的时间之间演变。它会自动遍历对象之间的引用,保存和恢复整个图形。
在序列化和反序列化过程中需要特殊处理的可序列化类应该实现以下方法:
private void writeObject(java.io.ObjectOutputStream 流)
抛出 IOException;
private void readObject(java.io.ObjectInputStream 流)
抛出 IOException,ClassNotFoundException;
私有无效 readObjectNoData()
抛出 ObjectStreamException;

readObject 方法负责使用由相应的 writeObject 方法写入流的数据读取和恢复其特定类的对象状态。该方法不需要关心属于它的超类或子类的状态。通过从 ObjectInputStream 中读取各个字段的数据并分配给对象的适当字段来恢复状态。 DataInput 支持读取原始数据类型。
任何读取超出由相应 writeObject 方法写入的自定义数据边界的对象数据的尝试都将导致抛出 OptionalDataException,eof 字段值为 true。超出分配数据末尾的非对象读取将以与指示流结束相同的方式反映数据的结束:逐字节读取将返回 -1 作为读取的字节或读取的字节数,以及原始数据读取将抛出 EOFExceptions。如果没有对应的 writeObject 方法,则默认序列化数据的结束标志着分配数据的结束。
从 readExternal 方法中发出的原始调用和对象读取调用的行为方式相同——如果流已经位于相应 writeExternal 方法写入的数据的末尾,则对象读取将抛出 OptionalDataExceptions 并将 eof 设置为 true,按字节读取将返回 -1,原始读取将抛出 EOFExceptions。请注意,此行为不适用于使用旧的 ObjectStreamConstants.PROTOCOL_VERSION_1 协议写入的流,在该协议中 writeExternal 方法写入的数据的结尾没有被划分,因此无法检测到。
readObjectNoData 方法负责在序列化流未将给定类列为被反序列化对象的超类的情况下为其特定类初始化对象的状态。在接收方使用与发送方不同版本的反序列化实例类的情况下,可能会发生这种情况,并且接收方的版本扩展了发送方版本未扩展的类。如果序列化流被篡改,也可能发生这种情况;因此,尽管存在“敌对”或不完整的源流,但 readObjectNoData 可用于正确初始化反序列化对象。
序列化不会读取或分配值给未实现 java.io.Serializable 接口的任何对象的字段。不可序列化的对象的子类可以是可序列化的。在这种情况下,不可序列化的类必须有一个无参数构造函数以允许初始化其字段。在这种情况下,子类负责保存和恢复不可序列化类的状态。通常情况下,该类的字段是可访问的(公共的、包的或受保护的),或者存在可用于恢复状态的 get 和 set 方法。
反序列化对象时发生的任何异常都将被 ObjectInputStream 捕获并中止读取过程。
实现 Externalizable 接口允许对象完全控制对象序列化形式的内容和格式。调用 Externalizable 接口的方法 writeExternal 和 readExternal 来保存和恢复对象状态。当由类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法写入和读取自己的状态。对象负责处理发生的任何版本控制。
枚举常量的反序列化与普通的可序列化或外部化对象不同。枚举常量的序列化形式仅由其名称组成;不传输常量的字段值。为了反序列化一个枚举常量,ObjectInputStream 从流中读取常量名;然后通过使用枚举常量的基类型和接收到的常量名称作为参数调用静态方法 Enum.valueOf(Class, String) 来获得反序列化的常量。与其他可序列化或可外部化对象一样,枚举常量可以作为随后出现在序列化流中的反向引用的目标。枚举常量的反序列化过程无法自定义:在反序列化过程中,将忽略枚举类型定义的任何特定于类的 readObject、readObjectNoData 和 readResolve 方法。类似地,任何serialPersistentFields 或serialVersionUID 字段声明也将被忽略——所有枚举类型都有一个固定的0L 的serialVersionUID。

public class ObjectInputStream extends InputStream implements ObjectInput,ObjectStreamConstants{
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值