java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > JavaIO流解析

Java中IO流解析及代码实例

作者:血莲丹

下面小编就为大家带来一篇关于Java中的IO流总结(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

I/O简介

I/O是Input/output的缩写,在java中,对于数据的输入和输出以流的方式进行。java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。 

输入输出都是基于内存的角度来说的。输入:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。 输出:输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

流的分类

操作数据单位不同分为:字节流(8 bit),字符流(16 bit)

数据流的流向不同分为:输入流,输出流

流的角色的不同分为:节点流,处理流  

节点流:直接从数据源或目的地读写数据。  

处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。 相当于是二次包装。

抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

Java的IO流共涉及40多个类,实际上非常规则,都是从这4个抽象基类派生的。由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

字节流和字符流常用API

InputStream

Reader

OutputStream

Writer

字节字符流相关操作

字节流读取文本内容

// 读取文本文件内容,用字节流去读,可能会乱码
    public void test1() {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("hello.txt");//相对路径是工程路径下
            int len;
            byte[] bytes = new byte[5];// 定义5字节长度的byte数组
            while ((len = inputStream.read(bytes)) != -1) {// 将数据读到byte数组中
                System.out.println(new String(bytes, 0, len)); //打印到控制台
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
	}

字符流读取文本内容

// 读取文本文件内容,用字符流去读,不会乱码,最多重复	
    public void test2() {
        Reader reader = null;
        try {
            reader = new FileReader("hello.txt");
            int len;
            char[] charBuff = new char[5];
            while ((len = reader.read(charBuff)) != -1) {
//                System.out.println(new String(charBuff)); // 注意这两行的代码区别
                System.out.println(new String(charBuff, 0, len));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

字节流读取文件到输出到指定位置

public void test3() {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new FileInputStream("hello.txt"); // 读取文件
            outputStream = new FileOutputStream("hello2.txt"); // 相对路径,默认是工程路径下
            int len;
            byte[] bytes = new byte[5];
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null){
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

字符流读取文件到输出到指定位置

字符流读取文件到输出到指定位置时,如果没有手动关闭流,则不会输出到指定位置,需要手动flush。但是如果在finally块中关闭了流,则会自动flush。在close()操作中,会帮我们flush。

public void test4() {
        Reader reader = null;
        Writer writer = null;
        try {
            reader = new FileReader("hello2.txt");
            writer = new FileWriter("hello3.txt");
            int len;
            char[] charBuff = new char[5];
            while ((len = reader.read(charBuff)) != -1) {
                writer.write(charBuff, 0, len);
//                writer.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (writer != null) { // 一定要关闭字符流,否则要手动flush
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

注意,字符流用来处理字符串很便捷,并且只能操作普通的文本文件,例如:.txt,.java,.c,.cpp 等语言的源代码。尤其注意.doc,excel,ppt这些不是文本文件。字节流既可以操做文本文件,也可以操作字节文件,比如.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt。如果用字符流来操作图片等字节文件,生成的文件是无法打开的!

缓冲流

为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用 8192个字节(8Kb) 的缓冲区。

缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为BufferedInputStream和ufferedOutputStream以及BufferedReader和BufferedWriter。分别对应字节缓冲流和字符缓冲流。相当于在字节和字符流上包装了一下。

BufferedInputStream和BufferedOutputStream

public void test() {
        InputStream inputStream ;
        OutputStream outputStream ;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            inputStream = new FileInputStream("modify.txt"); //小于8KB
            outputStream = new FileOutputStream("modify2.txt");
            bis = new BufferedInputStream(inputStream);
            bos = new BufferedOutputStream(outputStream);
            int len;
            byte[] bytes = new byte[5];
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

BufferedReader和BufferedWriter

public void test2() {
        Reader reader ;
        Writer writer ;
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            reader = new FileReader("modify.txt");
            writer = new FileWriter("modify2.txt");
            br = new BufferedReader(reader);
            bw = new BufferedWriter(writer);
            int len;
            char[] bytes = new char[5];
            while ((len = br.read(bytes)) != -1) {
                bw.write(bytes, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (bw != null){
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

**缓冲流如果没有手动关闭流,且读取的文件小于底层缓存大小8KB,是不会自动写到目标中去的,需要手动flush。**在关闭流时,只需关闭缓冲流即可,它会自动关闭它包装的底层节点流。

数据流

为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。数据流有两个类:DataInputStream和DataOutputStream, 别“套接”在InputStream和OutputStream子类的流上。

使用如下:

 public void test() {
        DataOutputStream dos = null;
        try {
            OutputStream outputStream = new FileOutputStream("data.txt");
            dos = new DataOutputStream(outputStream);
            dos.writeUTF("热烈庆祝中国共产党成立一百周年");
            dos.writeInt(100);
            dos.writeBoolean(true);
            System.out.println("成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (dos != null) {
                    dos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public void test2(){
        DataInputStream dis =  null;
        try {
            InputStream inputStream = new FileInputStream("data.txt");
            dis = new DataInputStream(inputStream);
            System.out.println(dis.readUTF()); //读取时要按照写入顺序读取
            System.out.println(dis.readInt());
            System.out.println(dis.readBoolean());
            System.out.println("成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (dis != null) {
                    dis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对象流

用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

序列化与反序列化的演示

先定义一个Person类,该类必须实现Serializable接口,否则序列化时会报java.io.NotSerializableException 的错误

package day07;
import java.io.Serializable;
import java.util.Date;
public class Person implements Serializable {
    private static final long serialVersionUID = -5858950242987134591L;
    private String name;
    private Integer age;
    private Date date;
    public Person(){}
    public Person(String name, Integer age, Date date) {
        this.name = name;
        this.age = age;
        this.date = date;
    }
  // getter、setter略
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", date=" + date +
                '}';
    }
}

序列化

    public void test() {
        ObjectOutputStream oos = null;
        try {
            OutputStream outputStream = new FileOutputStream("person.txt"); // 创建输出流对象,指定输出位置
            oos = new ObjectOutputStream(outputStream); // 包装输出流
            oos.writeObject(new Person("张三",22,new Date())); // 序列化对象
            System.out.println("序列化成功!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

反序列化

public void test2() {
        ObjectInputStream ois = null;
        try {
            InputStream inputStream = new FileInputStream("person.txt");
            ois = new ObjectInputStream(inputStream);
            Person person = (Person) ois.readObject();
            System.out.println("person姓名为:" + person.getName());
            System.out.println("person年龄为:" + person.getAge());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒");
            System.out.println("创建时间为:" + sdf.format(person.getDate()));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

在这里插入图片描述

无论如何反序列化,时间都是不变的。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

您可能感兴趣的文章:
阅读全文