Java笔记(17)IO流扩展

Java笔记(17)IO流扩展

1.IO流扩展

(1)数据操作流

这个流可以操作Java中的基本数据类型,可以将基本类型写入文件中或读取出。

主要有两个类:
    数据输入流:DataInputStream
    数据输出流:DataOutputStream

DataInputStream下的主要方法

构造方法:
DataInputStream(InputStream in) 
          使用指定的底层 InputStream 创建一个 DataInputStream。
成员方法:
 int read(byte[] b) 
          从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b 中。 
 int read(byte[] b, int off, int len) 
          从包含的输入流中将最多 len 个字节读入一个 byte 数组中。 
 boolean readBoolean() 
          参见 DataInput 的 readBoolean 方法的常规协定。 
 byte readByte() 
          参见 DataInput 的 readByte 方法的常规协定。 
 char readChar() 
          参见 DataInput 的 readChar 方法的常规协定。 
 double readDouble() 
          参见 DataInput 的 readDouble 方法的常规协定。 
 float readFloat() 
          参见 DataInput 的 readFloat 方法的常规协定。 
 void readFully(byte[] b) 
          参见 DataInput 的 readFully 方法的常规协定。 
 void readFully(byte[] b, int off, int len) 
          参见 DataInput 的 readFully 方法的常规协定。 
 int readInt() 
          参见 DataInput 的 readInt 方法的常规协定。 
 long readLong() 
          参见 DataInput 的 readLong 方法的常规协定。 
 short readShort() 
          参见 DataInput 的 readShort 方法的常规协定。 

DataOutputStream下主要方法:

构造方法:
DataOutputStream(OutputStream out) 
          创建一个新的数据输出流,将数据写入指定基础输出流。
成员方法:
 void flush() 
          清空此数据输出流。 
 int size() 
          返回计数器 written 的当前值,即到目前为止写入此数据输出流的字节数。 
 void write(byte[] b, int off, int len) 
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入基础输出流。 
 void write(int b) 
          将指定字节(参数 b 的八个低位)写入基础输出流。 
 void writeBoolean(boolean v) 
          将一个 boolean 值以 1-byte 值形式写入基础输出流。 
 void writeByte(int v) 
          将一个 byte 值以 1-byte 值形式写出到基础输出流中。 
 void writeBytes(String s) 
          将字符串按字节顺序写出到基础输出流中。 
 void writeChar(int v) 
          将一个 char 值以 2-byte 值形式写入基础输出流中,先写入高字节。 
 void writeChars(String s) 
          将字符串按字符顺序写入基础输出流。 
 void writeDouble(double v) 
          使用 Double 类中的 doubleToLongBits 方法将 double 参数转换为一个 long 值,然后将该 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。 
 void writeFloat(float v) 
          使用 Float 类中的 floatToIntBits 方法将 float 参数转换为一个 int 值,然后将该 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。 
 void writeInt(int v) 
          将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。 
 void writeLong(long v) 
          将一个 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。 
 void writeShort(int v) 
          将一个 short 值以 2-byte 值形式写入基础输出流中,先写入高字节。 
(2)内存操作流

有些时候我们在对数据进行读写操作时未必需要一个文件对象,这时我们可以使用内存操作流。

内存操作流主要有三种:

  1. ByteArrayInputStream、ByteArrayOutputStream
  2. CharArrayReader、CharArrayWriter
  3. StringReader、StringWriter

注意的是,上面三种内存操作流分别操作的是字节数组、字符数组、字符串;在读的时候他们的构造方法需要传入要读的数据数组,写的时候构造传递的是它们内部的缓冲区大小,其本质是相当于创建了一个数组来存储数据,当程序结束时这些数据也会消失,且这三种流的close方法都无意义,不需要关闭;

(3)打印流

打印流有两种,一种是字节打印流,一种是字符打印流。它们的特点是只操作目的地,不操作数据源,也就是只负责输出,而且可以操作任意类型的数据。

字节打印流:PrintStream

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。

方法摘要:

构造方法:
PrintStream(File file) 
          创建具有指定文件且不带自动行刷新的新打印流。 
PrintStream(File file, String csn) 
          创建具有指定文件名称和字符集且不带自动行刷新的新打印流。 
PrintStream(OutputStream out) 
          创建新的打印流。 
PrintStream(OutputStream out, boolean autoFlush) 
          创建新的打印流,当后面参数为true时启动自动刷新;
PrintStream(OutputStream out, boolean autoFlush, String encoding) 
          创建新的打印流,最后一个参数是字符集
PrintStream(String fileName) 
          创建具有指定文件名称且不带自动行刷新的新打印流。 
PrintStream(String fileName, String csn) 
          创建具有指定文件名称和字符集且不带自动行刷新的新打印流。 
成员方法:
void print(boolean b) 
          打印 boolean 值。 
 void print(char c) 
          打印字符。 
 void print(char[] s) 
          打印字符数组。 
 void print(double d) 
          打印双精度浮点数。 
 void print(float f) 
          打印浮点数。 
 void print(int i) 
          打印整数。 
 void print(long l) 
          打印 long 整数。 
 void print(Object obj) 
          打印对象。 
 void print(String s) 
          打印字符串。 
void println() 
          通过写入行分隔符字符串终止当前行。 
 void println(boolean x) 
          打印 boolean 值,然后终止行。 
 void println(char x) 
          打印字符,然后终止该行。 
 void println(char[] x) 
          打印字符数组,然后终止该行。 
 void println(double x) 
          打印 double,然后终止该行。 
 void println(float x) 
          打印 float,然后终止该行。 
 void println(int x) 
          打印整数,然后终止该行。 
 void println(long x) 
          打印 long,然后终止该行。 
 void println(Object x) 
          打印 Object,然后终止该行。 
 void println(String x) 
          打印 String,然后终止该行。 

字符打印流:PrintWriter

构造方法摘要 
PrintWriter(File file) 
          使用指定文件创建不具有自动行刷新的新 PrintWriter。 
PrintWriter(File file, String csn) 
          创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。 
PrintWriter(OutputStream out) 
          根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。 
PrintWriter(OutputStream out, boolean autoFlush) 
          通过现有的 OutputStream 创建新的 PrintWriter。 
PrintWriter(String fileName) 
          创建具有指定文件名称且不带自动行刷新的新 PrintWriter。 
PrintWriter(String fileName, String csn) 
          创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。 
PrintWriter(Writer out) 
          创建不带自动行刷新的新 PrintWriter。 
PrintWriter(Writer out, boolean autoFlush) 
          创建新 PrintWriter。 
方法摘要
void print(boolean b) 
          打印 boolean 值。 
 void print(char c) 
          打印字符。 
 void print(char[] s) 
          打印字符数组。 
 void print(double d) 
          打印 double 精度浮点数。 
 void print(float f) 
          打印一个浮点数。 
 void print(int i) 
          打印整数。 
 void print(long l) 
          打印 long 整数。 
 void print(Object obj) 
          打印对象。 
 void print(String s) 
          打印字符串。 
 void println() 
          通过写入行分隔符字符串终止当前行。 
 void println(boolean x) 
          打印 boolean 值,然后终止该行。 
 void println(char x) 
          打印字符,然后终止该行。 
 void println(char[] x) 
          打印字符数组,然后终止该行。 
 void println(double x) 
          打印双精度浮点数,然后终止该行。 
 void println(float x) 
          打印浮点数,然后终止该行。 
 void println(int x) 
          打印整数,然后终止该行。 
 void println(long x) 
          打印 long 整数,然后终止该行。 
 void println(Object x) 
          打印 Object,然后终止该行。 
 void println(String x) 
          打印 String,然后终止该行。 

注意的是,只有在构造上设置了true且使用println方法才可以启动自动刷新;

(4)标准输入输出流

在System类下我们可以发现有两个字段,in和out;它们对应的分别是标准输入流InputStream和标准输出流PrintStream;

通过这个标准输入流和标准输出流,我们可以实现控制台录入数据和输出数据。

三种键盘录入方式:

1.最早期的java版本程序会使用main方法的args参数进行键盘数据录入
	public static void mai(String[] args){
	}
2.Scanner
	jdk5以后可以用Scanner类实现键盘录入,本质是封装了一个标准输入流对象
	Scanner sc = new Scanner(System.in);
3.BufferedReader
	通过BufferedReader包装一个标准输入流进行键盘录入操作
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
(5)随机访问流

是一种可以按照文件指针位置进行写操作和读操作的流,注意的是他同时提供了读和写的方法,且不属于流的子类,它的父类是Object;

RandomAccessFile方法:

构造方法:
RandomAccessFile(File file, String mode) 
          创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。 
RandomAccessFile(String name, String mode) 
          创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。 
          mode是指操作模式,有r、rw、rws、rwd;常用模式是rw,即能读也能写
成员方法:
long getFilePointer() 
          返回此文件中的当前偏移量。 
 long length() 
          返回此文件的长度。 
 int read() 
          从此文件中读取一个数据字节。 
 int read(byte[] b) 
          将最多 b.length 个数据字节从此文件读入 byte 数组。 
 int read(byte[] b, int off, int len) 
          将最多 len 个数据字节从此文件读入 byte 数组。 
 boolean readBoolean() 
          从此文件读取一个 boolean。 
 byte readByte() 
          从此文件读取一个有符号的八位值。 
 char readChar() 
          从此文件读取一个字符。 
 double readDouble() 
          从此文件读取一个 double。 
 float readFloat() 
          从此文件读取一个 float。 
 void readFully(byte[] b) 
          将 b.length 个字节从此文件读入 byte 数组,并从当前文件指针开始。 
 void readFully(byte[] b, int off, int len) 
          将正好 len 个字节从此文件读入 byte 数组,并从当前文件指针开始。 
 int readInt() 
          从此文件读取一个有符号的 32 位整数。 
 String readLine() 
          从此文件读取文本的下一行。 
 long readLong() 
          从此文件读取一个有符号的 64 位整数。 
 short readShort() 
          从此文件读取一个有符号的 16 位数。 
 int readUnsignedByte() 
          从此文件读取一个无符号的八位数。 
 int readUnsignedShort() 
          从此文件读取一个无符号的 16 位数。 
 String readUTF() 
          从此文件读取一个字符串。 
 void seek(long pos) 
          设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。 
 void setLength(long newLength) 
          设置此文件的长度。 
 int skipBytes(int n) 
          尝试跳过输入的 n 个字节以丢弃跳过的字节。 
 void write(byte[] b) 
          将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。 
 void write(byte[] b, int off, int len) 
          将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。 
 void write(int b) 
          向此文件写入指定的字节。 
 void writeBoolean(boolean v) 
          按单字节值将 boolean 写入该文件。 
 void writeByte(int v) 
          按单字节值将 byte 写入该文件。 
 void writeBytes(String s) 
          按字节序列将该字符串写入该文件。 
 void writeChar(int v) 
          按双字节值将 char 写入该文件,先写高字节。 
 void writeChars(String s) 
          按字符序列将一个字符串写入该文件。 
 void writeDouble(double v) 
          使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,然后按八字节数量将该 long 值写入该文件,先定高字节。 
 void writeFloat(float v) 
          使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个 int,然后按四字节数量将该 int 值写入该文件,先写高字节。 
 void writeInt(int v) 
          按四个字节将 int 写入该文件,先写高字节。 
 void writeLong(long v) 
          按八个字节将 long 写入该文件,先写高字节。 
 void writeShort(int v) 
          按两个字节将 short 写入该文件,先写高字节。 
 void writeUTF(String str) 
          使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。 

案例:

		//创建随机访问流对象
		RandomAccessFile raf = new RandomAccessFile("2.txt", "rw");
		
		//设置文件指针为当前文件长度,保证每次写数据是在最后面写
		raf.seek(raf.length());
		//写数据
		raf.writeInt(100);
		raf.writeUTF("中国");
		
		//读数据,从第一位开始读
		raf.seek(0);
		System.out.println("当前文件指针位置:" + raf.getFilePointer());
		
		int a = raf.readInt();
		System.out.println(a);
		System.out.println("当前文件指针位置:" + raf.getFilePointer());
		raf.seek(raf.getFilePointer());
		
		String b = raf.readUTF();
		System.out.println(b);
		System.out.println("当前文件指针位置:" + raf.getFilePointer());
		
		raf.close();

控制台:
当前文件指针位置:0
100
当前文件指针位置:4
中国
当前文件指针位置:12

可以看到,文件指针是按照数据的字节长度前移的,这其中的中国按UTF应该是6个字节,但通过
API查看可以知道每次writeUTF时会先写两个与数据无关的字节,所以让中国字节长度变成8;
(6)合并流

合并输入流SequenceInputStream可以将多个输入流合并为一个输入流,实现将多个文件的内容写入到一个文件中。
构造方法:
SequenceInputStream(InputStream s1, InputStream s2)
SequenceInputStream(Enumeration<? extends InputStream> e)
多个输入流合并可以使用第二个构造方法,具体请查看API;

(7)序列化与反序列化流

什么是序列化与反序列化?

序列化:指把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。这个过程称为序列化。通俗来说就是将数据结构或对象转换成二进制串的过程

反序列化:把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。也就是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程

为什么要做序列化?

①、在分布式系统中,此时需要把对象在网络上传输,就得把对象数据转换为二进制形式,需要共享的数据的 JavaBean 对象,都得做序列化。

②、服务器钝化:如果服务器发现某些对象好久没活动了,那么服务器就会把这些内存中的对象持久化在本地磁盘文件中(Java对象转换为二进制文件);如果服务器发现某些对象需要活动时,先去内存中寻找,找不到再去磁盘文件中反序列化我们的对象数据,恢复成 Java 对象。这样能节省服务器内存。

Java 怎么进行序列化?

①、需要做序列化的对象的类,必须实现序列化接口:Java.lang.Serializable 接口(这是一个标志接口,没有任何抽象方法),Java 中大多数类都实现了该接口,比如:String,Integer

②、底层会判断,如果当前对象是 Serializable 的实例,才允许做序列化,Java对象 instanceof Serializable 来判断。

③、在 Java 中使用对象流来完成序列化和反序列化

ObjectOutputStream:通过 writeObject()方法做序列化操作

ObjectInputStream:通过 readObject() 方法做反序列化操作

在这里插入图片描述

序列化时有个注意的地方,当把一个类的对象通过序列化流写入文件时会产生一个序列化ID,此时如果你再去修改类后去读就会产生一个问题,这是因为此时的类对象的序列化ID和类的序列化ID不同,就会产生错误。为了解决这个问题,可以在定义类时直接给其一个固定的序列化id值即可;

(8)Properties类

Properties类是Hashtable的子类,是一个特殊的可以直接和IO流结合使用的集合类;
构造方法摘要:
Properties()
创建一个无默认值的空属性列表。
Properties(Properties defaults)
创建一个带有指定默认值的空属性列表。

方法摘要

 String getProperty(String key) 
          用指定的键在此属性列表中搜索属性。 
 String getProperty(String key, String defaultValue) 
          用指定的键在属性列表中搜索属性。 
 void list(PrintStream out) 
          将属性列表输出到指定的输出流。 
 void list(PrintWriter out) 
          将属性列表输出到指定的输出流。 
 void load(InputStream inStream) 
          从输入流中读取属性列表(键和元素对)。 
 void load(Reader reader) 
          按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 
 void loadFromXML(InputStream in) 
          将指定输入流中由 XML 文档所表示的所有属性加载到此属性表中。 
 Enumeration<?> propertyNames() 
          返回属性列表中所有键的枚举,如果在主属性列表中未找到同名的键,则包括默认属性列表中不同的键。 
 Object setProperty(String key, String value) 
 		  调用 Hashtable 的方法 put。 
 void store(OutputStream out, String comments) 
 		  以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 
 void store(Writer writer, String comments) 
 		  以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 
 Set<String> stringPropertyNames() 
          返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值