IO中Sream的理解

Stream

  • Java程序得到数据是输入流
  • Java程序对外提供数据是输出流
  • 输入和输出是以Java程序为核心的

流的分类

  • 输入流和输出流
    1.inputStream类是输入流的基类
    2.OutputSream类是输出流的基类
  • 字节流和字符流
    1.字节流的类名字都包含Stream
    2.字符流的类名中包含Reader或Writer
  • 转换流
    1.以字符流读取字节流
    2.以字符流写入字节流
  • 随机访问流:RandomAccessFile
  • 缓存流:利用缓冲区提示性能
  • 对象流:对象流就是序列化和反序列化
  • 数据流:数据流就是将指定的数据类型读取和写入

设计原则

Java的I/O库提供了一种称作链接的机制,可以将一个流与另一个流首尾相连,形成一个流管道的链接,通过流的链接,可以动态地增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。


流的操作流程

不管是输入流还是输出流,操作过程包括如下:
第一步:打开流:通过File类或者网络或者其他打开流
第二步:操作流:读写流
第三步:关闭流:以释放和这个流相关的系统资源

字节流

  • 字节流是由字节组成的,是byte类型

  • 字节流是采用ASCII编码的

  • 字节流主要用在处理二进制数据(图像,word等各种文件都是二进制的),是按字节来处理的,但实际中很多的数据是文本。

字节流的类体系结构如下图:


字节输出流OutputStream
OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法。

输出流中定义都是写write方法。

返回值 方法名 描述
void close() 关闭此输出流并释放与此流相关联的任何系统资源。
void flush() 刷新此输出流并强制任何缓冲的输出字节被写出。
void write(byte[] b) b.length字节从指定的字节数组写入此输出流。
void write(byte[] b,int off,int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。
void write(int b) 将指定的字节写入此输出流。

FileOutputStream类

OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。

返回值 方法名 描述
void close() 关闭此文件输出流并释放与此流相关联的任何系统资源。
void write(byte[] b) b.length个字节从指定的字节数组写入此文件输出流。
void write(byte[] b, int off, int len) len字节从位于偏移量 off的指定字节数组写入此文件输出流。
void write(int b) 将指定的字节写入此文件输出流。

#FileOutputStream类写入数据到文件中

public static void main(String[] args) throws IOException {
    //需求:将数据写入到文件中。
    //创建存储数据的文件。
    File file = new File("d:\\file.txt");//覆盖
    //File file = new File("d:\\file.txt",true);//第二个参数true,表示追加模式
    //创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
    //输出流目的是文件,会自动创建。如果文件存在,则覆盖。
    FileOutputStream fos = new FileOutputStream(file);
    //调用父类中的write方法。
    byte[] data = "abcde".getBytes();
    fos.write(data);
    //关闭流资源。
    fos.close();
}

给文件中续写和换行

我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?
查阅FileOutputStream的API。发现在FileOutputStream的构造函数中,可以接受一个boolean类型的值,如果值true,就会在文件末位继续添加。

构造函数 说明
FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。
FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。

:要在finally中关闭流

public static void main(String[] args) {
    File file = new File("d:\\file.txt");
    //定义FileOutputStream的引用
    FileOutputStream fos = null;
    try {
        //创建FileOutputStream对象
        fos = new FileOutputStream(file);
        //写出数据
        fos.write("abcde".getBytes());
    } catch (IOException e) {
        System.out.println(e.toString() + "----");
    } finally {
        //一定要判断fos是否为null,只有不为null时,才可以关闭资源
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                throw new RuntimeException("");
            }
        }
    }
}

字节输入流InputStream

InputStream 用于从源头(通常是文件)读取数据(字节信息)到内存中,java.io.InputStream 抽象类是所有字节输入流的父类。

返回值 方法名 说明
void close() 关闭此输入流并释放与流相关联的任何系统资源。
int read() 从输入流读取数据的下一个字节。
int read(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区 b
int read(byte[] b, int off, int len) 从输入流读取最多 len字节的数据到一个字节数组。

FileInputStream类

InputStream有很多子类,其中子类FileInputStream可用来读取文件内容。

FileInputStream 从文件系统中的某个文件中获得输入字节。

构造函数 说明
FileInputStream(File file) 通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

FileInputStream类读取数据read方法

返回值 方法名 说明
void close() 关闭此文件输入流并释放与流相关联的任何系统资源。
int read() 从该输入流读取一个字节的数据。
int read(byte[] b) 从该输入流读取最多 b.length个字节的数据为字节数组。
int read(byte[] b, int off, int len) 从该输入流读取最多 len字节的数据为字节数组。
public static void main(String[] args) throws IOException {
    File file = new File("d:\\file.txt");
    //创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
    FileInputStream fis = new FileInputStream(file);
    //读取数据。使用 read();一次读一个字节。
    int ch = 0;
    while ((ch = fis.read()) != -1) {
        System.out.println("ch=" + (char) ch);
    }
    // 关闭资源。
    fis.close();
}

读取数据read(byte[])方法

在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。

public static void main(String[] args) throws IOException {
    //演示第二个读取方法, read(byte[]);
    File file = new File("d:\\file.txt");
    // 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
    FileInputStream fis = new FileInputStream(file);
    //创建一个字节数组。
    byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。      
    int len = 0;
    while((len=fis.read(buf))!=-1){
        System.out.println(new String(buf,0,len));
    }
    fis.close();
}

读取数据read(byte[])方法

在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。

public static void main(String[] args) throws IOException {
    //演示第二个读取方法, read(byte[]);
    File file = new File("d:\\file.txt");
    // 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
    FileInputStream fis = new FileInputStream(file);
    //创建一个字节数组。
    byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。      
    int len = 0;
    while((len=fis.read(buf))!=-1){
        System.out.println(new String(buf,0,len));
    }
    fis.close();
}

中多个数据都读进内容中,然后在一次写出去,这样的速度一定会比前面代码速度快。

public static void main(String[] args) throws IOException {
    File srcFile = new File("d:\\images\\test.JPG");
    File destFile = new File("copyTest.JPG");
    // 明确字节流 输入流和源相关联,输出流和目的关联。
    FileInputStream fis = new FileInputStream(srcFile);
    FileOutputStream fos = new FileOutputStream(destFile);
    //定义一个缓冲区。
    byte[] buf = new byte[1024];
    int len = 0;
    while ((len = fis.read(buf)) != -1) {
        fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
    }
    // 关闭资源。
    fos.close();
    fis.close();
}

使用字节缓存流提升性能

字节缓冲流根据流的方向,共有2个

  • 写入数据到流中,字节缓冲输出流 BufferedOutputStream
  • 读取流中的数据,字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度

字节缓冲输出流BufferedOutputStream

构造函数 说明
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。

字节缓冲输入流 BufferedInputStream

构造函数 说明
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
BufferedInputStream(InputStream in, int size) 创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。

字符流

  • 字符流是由字符组成的
  • 字符由两个字节组成。1字符=2字节
  • 字符采用Unicode编码
  • 字符流支持中文,支持String类型
    字符流的类体系结构如下:

字符编码表

计算机底册数据存储都是二进制数据,每一个子符和一个整数对应起来,就形成了一张表
也叫编码表:生活中字符和计算机二级制的对应关系表。

  • ASCII
  • ISO-8859-1
  • GB2312
    1.GBK
    2.GBK18030
  • UNICODE
  • UTF-8

字符输入流Reader

上述程序中我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。

API中已经给我们提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类。

返回值 方法名 说明
int read() 读一个字符
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。

FileReader类

FileReader类是Reader类的子类,FileReader是用于读取字符流。

构造函数
FileReader(File file) 创建一个新的 FileReader ,给出 File读取。
FileReader(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。

FileReader读取包含中文的文件

public static void main(String[] args) throws IOException {
    //给文件中写中文
    writeCNText();
    //读取文件中的中文
    readCNText();
}
//读取中文
public static void readCNText() throws IOException {
    FileReader fr = new FileReader("D:\\cn.txt");
    int ch = 0;
    while((ch = fr.read())!=-1){
        //输出的字符对应的编码值
        System.out.println(ch);
        //输出字符本身
        System.out.println((char)ch);
    }
}
//写中文
public static void writeCNText() throws IOException {
    FileOutputStream fos = new FileOutputStream("D:\\cn.txt");
    fos.write("我是中文".getBytes());
    fos.close();
}

运行结果

25105

26159

20013

25991

字符输出流Writer

既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,Writer类就是专门写字符流的对象,是写入字符流的抽象类。

返回值 方法名 说明
abstract void close() 关闭流,先刷新。
abstract void flush() 刷新流。
void write(char[] cbuf) 写入一个字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符
void write(String str) 写一个字符串
void write(String str, int off, int len) 写一个字符串的一部分。

FileWriter类

FileWriter类是Writer类的子类,FileWriter 类用于写入字符流的抽象类。

构造函数
FileWriter(File file) 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。
FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。

FileWriter写入中文到文件中

public static void main(String[] args) throws IOException {
    FileWriter fw = new FileWriter("d:\\fw.txt");
    //FileWriter fw = new FileWriter("d:\\fw.txt",true);//第二个参数true,表示追加模式
    fw.write("山香红叶时叶红香山");//这些文字都要先编码。都写入到了流的缓冲区中。
    fw.flush();
    fw.close();
}

flush()和close()的区别

  • flush:将流中缓冲区缓冲的数据刷新到新的目的地中,刷新后,流任然可以使用
  • close():关闭资源,关闭前会将缓冲区的数据刷新到目的地,否自丢失数据,然后再关闭流。流不可以再使用

使用字符缓存流提升性能

字符缓冲输入流BufferedReader

  • BufferedReader 类从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
构造方法
BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) 创建使用指定大小的输入缓冲区的缓冲字符输入流。
返回值 方法名 说明
void close() 关闭流并释放与之相关联的任何系统资源。
int read() 读一个字符
int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。
String readLine() 读一行文字。

字符缓存输出流BufferedWriter

  • 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
构造函数 说明
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
返回值 方法名 说明
void close() 关闭流,先刷新。
void flush() 刷新流。
void newLine() 写一行行分隔符。
void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符
void write(String s, int off, int len) 写一个字符串的一部分。

转换流

OutputStreamWrite
OutputStreamWriter 是 Writer子类,是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。


构造函数
OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, Charset cs) 创建一个使用给定字符集的OutputStreamWriter。
返回值 方法名 说明
void close() 关闭流,先刷新。
void flush() 刷新流。
String getEncoding() 返回此流使用的字符编码的名称。
void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符
void write(String str, int off, int len) 写一个字符串的一部分。
public static void main(String[] args) throws IOException {
    File file = new File("haha1.txt");
    FileOutputStream fos = new FileOutputStream(file);
    OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
    BufferedWriter bw = new BufferedWriter(osw);
    bw.write("上海自来水来自海上");
    bw.flush();
    bw.close();
}

在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。

InputStreamReader类

构造函数
InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。
InputStreamReader(InputStream in, Charset cs) 创建一个使用给定字符集的InputStreamReader。
返回值 方法名 说明
void close() 关闭流并释放与之相关联的任何系统资源。
String getEncoding() 返回此流使用的字符编码的名称。
int read() 读一个字符
int read(char[] cbuf, int offset, int length) 将字符读入数组的一部分。
public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
        new File("haha1.txt")),"gbk"));
    String s = br.readLine();
    System.out.println(s);
    br.close();
}

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象

字节流与字符流的区别

字节流以字节为单位输入输出,8位二进制数
字符流以字符位单位输入输出,16二进制数

数据流

DateInputStream和DateInputStre提供读写Java中基本数据的功能。
在程序中写入字符串使用的是writeUTF方法,读取字符串使用的是readUTF方法,这两个方法是配对使用的。

DataInputStream

  • 数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。 应用程序使用数据输出流来写入稍后可以被数据输入流读取的数据。
构造函数
DataInputStream(InputStream in) 创建使用指定的底层InputStream的DataInputStream。
返回值 方法名
int read(byte[] b) 从包含的输入流中读取一些字节数,并将它们存储到缓冲区数组 b
int read(byte[] b,int off,int len) 从包含的输入流读取最多 len个字节的数据为字节数组。
boolean readBoolean() 见的总承包 readBoolean的方法 DataInput
byte readByte() 见的总承包 readByte的方法 DataInput
char readChar() readChar方法的总合同 DataInput
double readDouble() readDouble方法 DataInput的总体合同。
float readFloat() readFloatDataInput的一般合同。
int readInt() readInt方法 DataInput的一般合同。
long readLong() 见的总承包 readLong的方法 DataInput
short readShort() readShort方法 DataInput的一般合同。
String readUTF() readUTFDataInput的一般合同。

DataOutputStream

  • 数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流。 然后应用程序可以使用数据输入流来读取数据。
构造函数
DataOutputStream(OutputStream out) 创建一个新的数据输出流,以将数据写入指定的底层输出流。
返回值 方法名 说明
void flush() 刷新此数据输出流。
int size() 返回计数器的当前值 written ,到目前为止写入此数据输出流的字节数。
void write(byte[] b, int off, int len) 写入 len从指定的字节数组起始于偏移 off基础输出流。
void write(int b) 将指定的字节(参数 b的低8位)写入底层输出流。
void writeBoolean(boolean v) boolean写入底层输出流作为1字节值。
void writeByte(int v) byte作为1字节值写入底层输出流。
void writeBytes(String s) 将字符串作为字节序列写入基础输出流。
void writeChar(int v) char写入底层输出流作为2字节值,高字节优先。
void writeChars(String s) 将字符串写入底层输出流作为一系列字符。
void writeDouble(double v) 双参数传递给转换 long使用 doubleToLongBits方法在类 Double ,然后写入该 long值基础输出流作为8字节的数量,高字节。
void writeFloat(float v) 浮子参数的转换 int使用 floatToIntBits方法在类 Float ,<br />然后写入该 int值基础输出流作为一个4字节的数量,高字节。
void writeInt(int v) 将底层输出流写入 int作为四字节,高位字节。
void writeLong(long v) long写入底层输出流,为8字节,高字节为首。
void writeShort(int v) short写入底层输出流作为两个字节,高字节优先。
void writeUTF(String str) 使用 modified UTF-8 编码以机器无关的方式将字符串写入基础输出流。

持久化保存对象状态

public class Student {
    private String name;
    private int age;
    
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
/**
 * 需求:将对象的属性值写入到文件中保存
 * DataOutputStream是专门读写基本类型和String类型
 */
public class DataOutputSteamDemo {

    public static void main(String[] args) throws IOException {
        Student s[] = {
            new Student("sunmer", 100),
            new Student("华夏", 80)
        };
        
        File file =new File("d:/data.txt");
        FileOutputStream fos =new FileOutputStream(file);
        BufferedOutputStream bos =new BufferedOutputStream(fos);
        DataOutputStream dos = new DataOutputStream(bos);
        for (int i = 0; i < s.length; i++) {
            dos.writeUTF(s[i].getName());
            dos.writeInt(s[i].getAge());
        }
        dos.close();
        bos.close();
        fos.close();
    }
}
/**
 * 需求:将对象的属性值从文件中读取回来,重新构建对象
 * DataInputStream是专门读写基本类型和String
 */
public class DataInputStreamDemo {
    public static void main(String[] args) throws Exception {
        File file =new File("d:/data.txt");
        FileInputStream fis =new FileInputStream(file);
        BufferedInputStream bis =new BufferedInputStream(fis);
        DataInputStream dis =new DataInputStream(bis);
        String name1 = dis.readUTF();
        int age1 = dis.readInt();
        Student s1 = new Student(name1, age1);
    
        String name2 = dis.readUTF();
        int age2 = dis.readInt();
        Student s2 = new Student(name2, age2);
    
        dis.close();
        bis.close();
        fis.close();
        
        System.out.println(s1);
        System.out.println(s2);
    }
}   

对象流(序列化和反序列化)

ObjectOutputStream和ObjectInputStream
Java中的对象在程序运行期间保存在内存中,当程序运行结束,JVM退出,进程的地址空间被清理,所有对象都会被清除。
所以我们需要使用对象流来保存对象的状态**(状态:对象的属性名称和属性值)

  • 序列化:将对象的属性名称和属性值保存到文件中存储

  • 反序列化:将对象从文件中读取回内存,还原对象

对象序列化流ObjectOutputStream

ObjectOutputStream是FileOutputStream的子类,用于实现序列化,即向输出流中写入对象。

构造方法
protected ObjectOutputStream()
返回值 方法名 说明
void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。

反序列化对象流ObjectInputStream

  • ObjectInputStream是InputStream的子类,用于反序列化,即从输入流中读取对象。

  • 使用反序列化来恢复对象时,必须还必须能够找到该对象所属类的字节码文件。

构造函数
protected ObjectInputStream()
返回值 方法名 说明
Object readObject() 从ObjectInputStream读取一个对象。

序列化接口Serializable

当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。

Serializable接口是一个空接口,里面没有定义任何成员。该接口给需要序列化的类,提供了一个序列版本号,serialVersionUID。该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

序列化对象

序列化Worker对象

public class Worker implements Serializable{
    private String name;
    private int age;
    
    public Worker(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }   
    @Override
    public String toString() {
        return "Worker{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
}
/**
 * 序列化
 * 注意:需要序列化的对象必须实现Serializable接口
 *
 */
public class ObjectOutputStreamDemo {
    public static void main(String[] args) {
        write();
    }

    private static void write() {
        File file =null;
        FileOutputStream fos =null;
        BufferedOutputStream bos =null;
        ObjectOutputStream oos =null;
        try {
            file = new File("d:/data.yfq");
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            oos = new ObjectOutputStream(bos);
            
            Worker w1 = new Worker("时传祥", 20);
            Worker wc = new Worker("王进喜", 21);
            
            oos.writeObject(w1);
            oos.writeObject(wc);
            
            oos.flush();
            System.out.println("序列化结束");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

反序列化对象

/**
 * 反序列化
 */
public class ObjectInputSteamDemo {

    public static void main(String[] args) {
        read();

    }

    private static void read() {
        File file = null;
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        ObjectInputStream ois  = null;
        try {
            file = new File("d:/data.yfq");
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            ois = new ObjectInputStream(bis);
            Worker w1 = (Worker)ois.readObject();
            System.out.println(w1);
            Worker wc = (Worker)ois.readObject();
            System.out.println(wc);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

瞬态关键字transient

  • 当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会被序列化了。

  • 同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

随机访问流(RandomAccessFile)

只对文件进行读写操作,使用RandomAccessFile会更加方便。这个类与输入输出流没有关系,是直接Object继承的。

  • public long getFilePointer() throws IOException

    要移动文件指针,可以调用seek方法,该方法的签名如下所示:

  • public void seek(long pos) throws IOException

    参数pos是偏移的位置从文件开头、以字节为单位来测量。
    除了基本的读写方法外,RandomAccessFile也支持对Java基本数据类型的读写操作。RandomAccessFile类在构造时,需要指定文件的访问模式。
    除了基本的读写方法外,RandomAccessFile也支持对Java基本数据类型的读写操作。RandomAccessFile类在构造时,需要指定文件的访问模式。
    关于临时文件:
    temp目录是临时目录
    开发中建议用tmp表示临时目录,或者临时文件的文件名的开头。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容