Java中的IO流

流的概念

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。数据在两设备间的传输称为流,流的本质是数据传输。

Java中流的分类

根据处理数据类型的不同分为:字节流和字符流

  • 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

  • 字节流和字符流的区别:

读写单位不同:

字节流以byte字节(8个bit)为单位;
字符流以char字符(2个byte)为单位,根据码表映射字符,一次可能读多个字节。

处理对象不同:

字节流能处理所有类型的数据(如图片、avi等);
而字符流只能处理字符类型的数据。
  • 结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

根据数据流向不同分为:输入流和输出流

输入流只能进行读操作;
输出流只能进行写操作。 

程序中需要根据待传输数据的不同特性而使用不同的流。

字节流

字节输入流(FileInputStream)和字节输出流(FileOutputStream)

  • 使用字节流读取本地文本打印出来并写入另一个文本

    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        // 相对路径
        //fis = new FileInputStream("a.txt");
        // 绝对路径
        //fis = new FileInputStream("C:/workspace/IOStream/a.txt");
    
        fis = new FileInputStream(new File("a.txt"));
        fos = new FileOutputStream("b.txt");
        //在原来的数据后面添加(不覆盖)
        //fos = new FileOutputStream("b.txt",true);
        int len;
        //每读一次就写一次到本地文本(效率不高)
        while ((len = fis.read()) != -1) {
            System.out.print((char) len + ",");
            fos.write(len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fis.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

**注意:
1、本地文本内容不能是中文,否则打印输出时会出现乱码(写入另一个文本时不会乱码)。
2、注意流使用完毕后必须关闭(后面的例子一样,不再赘述)**

  • 使用byte数组缓冲区读取并写入文本

    FileInputStream fis = new FileInputStream("a.txt");
    FileOutputStream fos = new FileOutputStream("c.txt");
    byte[] array = new byte[8*1024];
    int len;
    // 读取文本数据每填满字节数组array就一次写到本地。(效率高)
    while ((len = fis.read(array)) != -1) {
        System.out.println(new String(array, 0, len));
        // 将字节数组中的文件写到文件上去
        fos.write(array, 0, len);
    }
    fis.close();
    fos.close();
    

**注意:
1、此时即便要读取的文本有中文,打印输出时候也不一定会有乱码(在读取文本的内容小于缓冲区字节数组内容时。当然也有肯能大于,所以不推荐这样使用,复制中文可以用字符流)。
2、除了复制文本也可以复制图片、音乐等。使用缓冲区能提高效率**

  • 使用Buffered缓冲区复制文件

    FileInputStream fis = new FileInputStream("butterfly.mp3");
    // 创建缓冲区输入流对象,对fis进行包装
    BufferedInputStream bis = new BufferedInputStream(fis);
    FileOutputStream fos = new FileOutputStream("Havorld.mp3");
    // 创建缓冲区输出流对象,对fos进行包装
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    
    // bis.read()会先将文件上的数据读到缓冲区中,再从缓冲里获取数据
    int b;
    while ((b = bis.read()) != -1) {
        // bos.write(b)是先将字节写到缓冲区里,然后在从缓冲区中一起写出
        System.out.print((char) b + "");
        bos.write(b);
    }
    bis.close();
    bos.close();    
    

    **
    注意:
    1、使用Buffered缓冲区如果有中文,在输出打印时会出现乱码。
    2、Buffered缓冲区的大小是8*1024个字节也就是8M。**

字符流

字符输入流(FileReader)和字符输出流(FileWriter)

  • 使用字符流读取中文打印出来并写入另一个文本

    FileReader fr = new FileReader("d.txt");
    FileWriter fw = new FileWriter("f.txt");
    int len;
    while ((len = fr.read()) != -1) {
        System.out.print((char) len + ",");
        fw.write(len);
    }
    fr.close();
    fw.close();
    

    **注意:
    1、字符流不能用于读写图片、音乐文件。
    2、字符流加缓冲区同字节流(BufferedReader,BufferedWriter),此处不再赘述。**

关于中文文字总结

  1. 从文件读取中文(字符)打印输出时,不能使用字节流(会出现乱码),用字符流。
  2. 向文件中写入中文(字符)时,可以用字节流,也可以用字符流。

    //字节流写入中文
    FileOutputStream fos = new FileOutputStream("e.txt");
    fos.write("Hi,你们好吗".getBytes());
    fos.write("\n".getBytes());
    fos.write(97);
    fos.write("b".getBytes());
    fos.close();
    
    //字符流写入中文
    FileWriter fw = new FileWriter("e.txt");
    fw.write("hello,掌声在哪里");
    fw.close(); 
    
  3. 复制中文文字(字符)时。可以使用字节流,也可以使用字符流,优先使用字节流(效率高)。

转换流InputStreamReader和OutputStreamWriter

转换流使用场景

  1. 当字节和字符之间有转换动作时;
  2. 流操作的数据需要编码或解码时。

当从一个UTF-8格式的文本中读取中文并写到GBK格式的文本中时需要用到转换流

    //字节流(FileInputStream)转换成了字符流(InputStreamReader),同时指定了编码
    InputStreamReader isr = new InputStreamReader(new FileInputStream("x.txt"), "UTF-8");
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("y.txt"), "GBK");

    int ch;
    while((ch = isr.read()) != -1) {
        osw.write(ch);
    }

    //同时也可以加上Buffered缓冲区
    /*
    BufferedReader br = new BufferedReader(isr);
    BufferedWriter bw = new BufferedWriter(osw);
    int ch;
    while((ch = br.read()) != -1) {
        bw.write(ch);
    }
    */
    isr.close();
    osw.close();

内存输出流ByteArrayOutputStream

    FileInputStream fis = new FileInputStream("note.txt");
    //内存输出流:一般操作文本,溢出的可能性很小(当是大文件时就容易内存溢出)
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int len;
    while((len = fis.read()) != -1) {
      //把输入流全部写入内存,然后再全部输出
        baos.write(len); 
    }
    byte[] array = baos.toByteArray();
    System.out.println(new String(array));  //输出
    System.out.println(baos);
    fis.close();

DataInputStream和DataOutputStream

通过DataInputStream获取文件中的内容输出打印出来,然后通过DataOutputStream写到另一个文件中

    DataInputStream dis = new DataInputStream(new FileInputStream("DataInput.txt"));
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("DataOutput.txt"));
    int len = 0;
    byte[] buffer = new byte[8 * 1024];
    while ((len = dis.read(buffer)) != -1) {
        dos.write(buffer, 0, len);
        dos.flush();//刷新缓冲区
        System.out.println(new String(buffer));
    }
    dis.close();        
    dos.close();

存取JavaBean中的基本数据类型

public static void main(String[] args) throws IOException {

    Student[] students = { new Student("Havorld", 22), new Student("Jack", 18), new Student("Sunny", 17) };
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("Havorld.txt"));
    for (Student student : students) {
        // 按UTF-8的格式写入字符串
        dos.writeUTF(student.getName());
        // 写入int数据
        dos.writeInt(student.getAge());
    }

    // 所有数据至目的地
    dos.flush();
    // 关闭流
    dos.close();

    DataInputStream dis = new DataInputStream(new FileInputStream("Havorld.txt"));

    // 读出数据并还原为对象
    for (int i = 0; i < students.length; i++) {
        // 读出UTF字符串
        String name = dis.readUTF();
        // 读出int数据
        int age = dis.readInt();
        students[i] = new Student(name, age);
    }

    // 关闭流
    dis.close();
    // 显示还原后的数据
    for (Student student : students) {
        System.out.printf("%s\t%d%n", student.getName(), student.getAge());
    }
}

创建JavaBean Student类

class Student implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    public Student(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 "Student [name=" + name + ", age=" + age + "]";
    }

}

读写对象流ObjectInputStream和ObjectOutputStream

使用ObjectInputStream和ObjectOutputStream保存和读取对象

public static void main(String[] args) throws ClassNotFoundException, IOException {

    ObjectOutputStream objectwriter = new ObjectOutputStream(new FileOutputStream("student.txt"));
    objectwriter.writeObject(new Student("Havorld", 22));
    objectwriter.writeObject(new Student("Jack", 18));
    objectwriter.writeObject(new Student("Sunny", 17));
    ObjectInputStream objectreader = new ObjectInputStream(new FileInputStream("student.txt"));
    for (int i = 0; i < 3; i++) {
        System.out.println(objectreader.readObject());
    }
    objectwriter.close();
    objectreader.close();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值