美文网首页
Java IO流

Java IO流

作者: dawsonenjoy | 来源:发表于2018-12-10 15:40 被阅读0次

IO流

java.io.*包下,按数据流方向分为输入/输出流;按处理数据单位分为字符流(Reader/Writer)和字节流(InputStream/OutputStream);按功能不同分为节点流和处理流(又称为包装流,包装在别的流外边,关闭时只需关闭最外层的处理流即可)

流通用步骤

1.创建资源对象
2.创建字节(/字符)输入(/输出)源对象
3.具体的读取(/写入)源内容操作
4.关闭输入(/输出)对象和源对象

FileInputStream/FileOutputStream

文件输入/输出字节流,其中输出字节流默认为w(覆盖)模式,如果要改为a(追加)模式,则在实例化的第二个参数里设置为true。其提供了常用方法如下:
1.read():输入流下的方法,该方法有以下几种传参方法:read(byte)/read(byte[])/read(byte[], index, len),分别为读取单个字节;读取一定长度字节并从索引位置为0开始存入字节数组;读取一定长度字节并从索引位置开始存入字节数组。当读取位置内容为空,则会返回-1;第二种方法返回的是读取的字节长度,如果读取长度为0,则也返回-1
2.write():输出流下的方法,该方法有以下几种传参方法:write(byte)/write(byte[])/write(byte[], index, len),分别为传入单个字节/传入字节数组/从索引位置开始传入一定长度的字节数组
使用举例:

import java.io.*;
public static void main(String[] args){
    int b = 0;
    FileInputStream in = null;
    FileOutputStream out = null;
    try{
        in = new FileInputStream("f:/a/1.txt"); //读取文件内容
        out = new FileOutputStream("f:/a/2.txt");   //输出内容到文件,默认w模式,第二个参数如果设置为true,则为a模式
        while((b=in.read())!=-1){
            out.write(b);
        }
        in.close();
        out.close();
        System.out.println("文件复制成功!");
    }catch(FileNotFoundException e){
        System.out.println("找不到文件!");
        System.exit(-1);
    }catch(IOException e){
        System.out.println("文件读取错误!");
        System.exit(-1);
    }

注:
资源使用后需要记得关闭,但是手动关闭十分麻烦,而且上面的代码也没用很好处理关闭时的异常,于是可以使用jdk1.7后提供的新特性里try语句的新用法:try(资源对象){异常语句}catch(){},其会在使用完资源对象后自动关闭,举例:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class test {
    public static void main(String[] args) throws Exception {
        int b = 0;
        try (   //jdk 1.7后新特性,将需要结束后关闭的资源对象代码放这里,将会自动关闭资源
                FileInputStream in = new FileInputStream("f:/a/1.txt");
                FileOutputStream out = new FileOutputStream("f:/a/2.txt");
            ) { //这里放可能会出现异常的代码
            while ((b = in.read()) != -1) {
                out.write(b);
            }
            // in.close(); //会自动关闭资源,不需要手动关闭
            // out.close();
            System.out.println("文件复制成功!");
        } catch (FileNotFoundException e) {
            System.out.println("找不到文件!");
            System.exit(-1);
        } catch (IOException e) {
            System.out.println("文件读取错误!");
            System.exit(-1);
        }
    }
}

FileReader/FileWriter

文件输入输出字符流,直接把上面的InputStream/OutputStream换成Reader/Writer就行,但要注意的是输出流的内容需要执行flush()以后才能将内容从内存读写到磁盘当中,在执行close()之前JVM也会自动调用一次flush()

BufferedInputStream/BufferOutputStream

缓冲输入输出字节流,是一种处理流,即包在节点流/处理流之上,会在内容先写到内存缓冲区,之后再一起写入到硬盘,举例:

int b = 0;
try{
    BufferedInputStream bin = new BufferedInputStream(new FileInputStream("f:/a/1.txt"));   //包在节点流之上
    BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("f:/a/2.txt"));
    while((b=bin.read())!=-1){
        bout.write(b);
        System.out.println((char)b);    //转字符后输出,否则输出的是数字
    }
    bout.flush();   //先把缓冲区的都写进硬盘
    bout.close();   //然后在关闭
    bin.close();
    System.out.println("文件复制成功!");
}catch

同样缓冲流中也有BufferedReader/BufferedWriter的字符流,其中BufferedReader提供了readLine()方法,支持一行一行读取

InputStreamReader/InputStreamWriter

转换流,可以进行将字节输入(/输出)流转换成字符输入(/输出)流,也是处理流的一种,举例:

int b = 0;
try{
    FileInputStream in = new FileInputStream("f:/a/1.txt");
    OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("f:/a/2.txt", true), "gbk");   //第一个参数是节点/处理流,第二个是编码格式
    while((b=in.read())!=-1){
        out.write(b);
    }
    System.out.println(out.getEncoding());  //输出GBK
    out.close();
}

DataInputStream/DataOutputStream

数据流,处理流的一种

PrintWriter/PrintStream

打印流,处理流的一种,只有输出流,其输出操作不会抛出异常,并且当调用printf/println/format时会进行自动刷新(flush()),如果没有开启自动刷新,则当缓冲区满时会进行自动刷新

PipeInputStream/PipeOutputStream

管道流,可以实现两个线程之间的数据交互

序列化和反序列化

https://www.cnblogs.com/xdp-gacl/p/3777987.html

实现序列化和反序列化

ObjectOutputStream/ObjectInputStream

实现对象序列化和反序列化的包装流,只能将支持序列化标记接口Serializable的对象写入流中,举例:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class test {
    public static void main(String[] args) throws Exception {
        //序列化
        File file = new File("f:/a/1.txt");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
        out.writeObject(new Stu(100, "aaa"));   //将Stu对象序列化至文件当中
        out.close();
        
        //反序列化
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        Stu stu = (Stu)in.readObject();
        System.out.println(stu);    //id:100,name:aaa
        in.close();
    }
}

class Stu implements Serializable { // 继承序列化接口
    private int id;
    private String name;

    public Stu(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String toString() {
        return "id:" + this.id + ",name:" + this.name;
    }
}

对于上面那样的一般情况,序列化会把所有的内容都进行反序列化,但是如果像密码这样不希望被反序列化的数据,那么可以通过设置成静态和瞬态变量来实现,其中瞬态变量可以通过关键字transient修饰完成。举例:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class test {
    public static void main(String[] args) throws Exception {
        //序列化
        File file = new File("f:/a/1.txt");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
        out.writeObject(new Stu(100, "aaa", "bbb"));
        out.close();
        
        //反序列化
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        Stu stu = (Stu)in.readObject();
        System.out.println(stu);    //id:100,name:aaa,password:null,可以看到password字段内容没有被访问到
        in.close();
    }
}

class Stu implements Serializable {
    private int id;
    private String name;
    transient String password;  //设置瞬态变量

    public Stu(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public String toString() {
        return "id:" + this.id + ",name:" + this.name + ",password:" + this.password;
    }
}
序列化版本问题

对于序列化对象,如果该对象的类被修改后再进行反序列化,那么就会发现因为序列化版本不同的问题而无法成功反序列化。因此有下面的解决方案:给类设置版本号,举例:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class test {
    public static void main(String[] args) throws Exception {
        //序列化
        File file = new File("f:/a/1.txt");
//      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
//      out.writeObject(new Stu(100, "aaa", "bbb"));  //先进行序列化,然后修改类的内容
//      out.close();
        
        //反序列化
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        Stu stu = (Stu)in.readObject();
        System.out.println(stu);    //把password内容都注释后读取,会发现依然可以反序列化,结果变成:id:100,name:aaa
        in.close();
    }
}

class Stu implements Serializable {

    private static final long serialVersionUID = 1L;    //设置版本号
    private int id;
    private String name;
    transient String password;

    public Stu(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public String toString() {
        return "id:" + this.id + ",name:" + this.name + ",password:" + this.password;
    }
}

注:
前面的序列化标记接口是不可控制的,如果想要可以自己控制序列化过程那么可以使用Externalizable接口

相关文章

  • Java之IO流详解

    title: Java之IO流详解tags: Java IO流categories: Java IO流 大多数应用...

  • 从0开始复习java(9)--IO

    Java的io通过java.io包下的类和接口支持。主要有输入、输出流,又分为字节流和字符流。Java的io流使用...

  • java IO入门笔记

    1.java IO流的概念,分类,类图 1.1. java IO 流的概念 java的io是实现输入和输出的基础,...

  • Java IO详解

    1 Java IO流的概念,分类 1.1 Java IO流的概念 java的IO是实现输入和输出的基础,可以方便的...

  • Java的IO和NIO

    Java的IO和NIO 一、Java的IO Java的IO功能在java.io包下,包括输入、输出两种IO流,每种...

  • java io 流

    java io 流 io 流总览 io 流主要提供四个接口 InputStream: 输入字节流 OutputSt...

  • 28、说说Java 中 IO 流

    说说Java 中 IO 流 Java 中 IO 流分为几种? 1、按照流的流向分,可以分为输入流和输出...

  • java IO流

    java IO流 java流操作的类和接口 java流类图结构 IO流的定义 流是一组有顺序的,有起点和终点的字节...

  • 05-Java中的IO与NIO面试题(15题)

    1、Java 中 IO 流? Java 中 IO 流分为几种?按照流的流向分,可以分为输入流和输出流;按照操作单元...

  • Java的IO和NIO

    一、IO java的IO功能都在java.io包下,包括输入输出两种IO流,每种输入输出流又可分为字节流和字符流两...

网友评论

      本文标题:Java IO流

      本文链接:https://www.haomeiwen.com/subject/duomcqtx.html