Java基础—IO小结(二)缓冲流与其它流的使用

一、缓冲流的使用

  每个字节流都有对应的缓冲流:

  

  BufferedInputStream / BufferedOutputStream

  构造器:

  

  

  方法摘要与对应节点流类似

  使用缓冲流实现文件复制:实际中也是;其中流的关闭只需要关闭缓冲流,内部嵌套的字节流会自动关闭。

@Test
    public void testBuffered1() {
        // 同样需要先关联文件,注意文本使用Reader Writer,非文本使用fis fos
        File file1 = new File("D:\\test\\1.jpg");
        File file2 = new File("D:\\test\\2.jpg");
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            // 创建节点流
            FileInputStream fis = new FileInputStream(file1);
            FileOutputStream fos = new FileOutputStream(file2);
            // 将节点流包装为缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            // 准备缓冲的数组
            byte[] bytes = new byte[20];
            int len;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
                // 写完后将最后的进行刷新一下
                bos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流,注意流的关闭顺序,直接关闭缓冲流时,会自动先关闭对应节点流
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

BufferedReader与BufferedWriter的使用也是与对应节点流类似

  演示独有的readLine方法:

@Test
    public void testBufferedReader() {
        File file1 = new File("D:\\test\\hello.txt");
        BufferedReader br = null;
        try {
            FileReader fr = new FileReader(file1);
            br = new BufferedReader(fr);
            // 使用br独有的读行的操作
            String s = null;
            while ((s = br.readLine()) != null) {
                System.out.println(s);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

// 注意,读取doc文档需要使用字节流(即使文档全部是文本组成,doc也已经不是纯文本文件了)

二、转换流的使用

  InputStreamReader / OutputStreamWriter

  JDK中的介绍如下:需要分清编码与解码的过程

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:

 BufferedReader in
   = new BufferedReader(new InputStreamReader(System.in));

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。

为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

 Writer out
   = new BufferedWriter(new OutputStreamWriter(System.out));

代理对 是一个字符,它由两个 char 值序列表示:高 代理项的范围为 ‘\uD800‘ 到 ‘\uDBFF‘,后跟范围为 ‘\uDC00‘ 到 ‘\uDFFF‘ 的低 代理项。

错误代理元素 指的是后面不跟低代理项的高代理项,或前面没有高代理项的低代理项。

此类总是使用字符集的默认替代序列 替代错误代理元素和不可映射的字符序列。如果需要更多地控制编码过程,则应该使用 CharsetEncoder 类。

  

  解码,解成我们能够看得懂的,也就是解成字符串

  简单示例如下:(不是特别重要,不作特别介绍这里)

@Test
    public void test1() {
        File file = new File("D:\\test\\hello.txt");
        // 异常处理暂略
        FileInputStream fis = new FileInputStream(file);
        // 字节流到字符流的解码
        InputStreamReader isr = new InputStreamReader(fis, "GBK");
        BufferedReader br = new BufferedReader(isr);
        String s;
        // 缓冲流的操作略去
    }

三、标准输入输出流

  

  也就是我们常见的Syetem.out/in

  接收用户输入使用示例:

@Test
    public void test1() {
        BufferedReader br = null;
        try {
            InputStream in = System.in;
            // 转换成字符流
            InputStreamReader isr = new InputStreamReader(in);
            br = new BufferedReader(isr);
            String s;
            while (true) {
                System.out.println("请输入字符串:");
                s = br.readLine();
                if ("exit".equalsIgnoreCase(s)) {
                    break;
                }
                String s1 = s.toUpperCase();
                System.out.println(s1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

四、其它流

  1.打印流

  打印流都是输出流,所以分为两个:字节打印流和字符打印流

  

  像我们常用的Sytem.out返回的就是一个打印流

  关于打印流的信息,请参见 酒香逢 的随笔:http://www.cnblogs.com/fnz0/p/5423201.html

  2.数据流

  用来处理基本数据类型(包括String等)

  

  数据流请参见:http://baihe747.iteye.com/blog/2072146

  3.对象流

    推荐的序列化与反序列工具是hutool的ObjectUtil的相关方法!

  

  序列化:

  

  

  序列化一个类的示例:(必须实现相关接口,并且属性也需要实现Serializable接口)——ObjectOutputStream

@Test
    public void test1() {
        // 对象
        Person p1 = new Person("小明", 18);
        Person p2 = new Person("小红", 23);
        ObjectOutputStream oos = null;
        try {
            // 对象流
            FileOutputStream fos = new FileOutputStream(new File("person.txt"));
            oos = new ObjectOutputStream(fos);
            oos.writeObject(p1);
            oos.writeObject(p2);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
class Person implements Serializable{
    String name;
    Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ‘}‘;
    }
}

应当加上版本号声明:

class Person implements Serializable{
    private static final long serialVersionUID = 1L;

结果:

  

  反序列化:——ObjectInputStream

@Test
    public void test2() {
        ObjectInputStream ois = null;
        try {
            FileInputStream fis = new FileInputStream(new File("person.txt"));
            ois = new ObjectInputStream(fis);
            // 反序列化到内存中了
            Person p1 = (Person) ois.readObject();
            System.out.println("p1 = " + p1);
            Person p2 = (Person) ois.readObject();
            System.out.println("p2 = " + p2);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

结果:

  

  当然,除了上述的文件流,我们还可以进行byte[]数组流的序列化与反序列化,相关的工具类,推荐如下:

package cn.itcast_03_netty.sendobject.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ByteObjConverter {
    /**
     * 使用IO的inputstream流将byte[]转换为object
     * @param bytes
     * @return
     */
    public static Object byteToObject(byte[] bytes) {
        Object obj = null;
        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
        ObjectInputStream oi = null;
        try {
            oi = new ObjectInputStream(bi);
            obj = oi.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bi.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                oi.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return obj;
    }
    /**
     * 使用IO的outputstream流将object转换为byte[]
     * @param bytes
     * @return
     */
    public static byte[] objectToByte(Object obj) {
        byte[] bytes = null;
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = null;
        try {
            oo = new ObjectOutputStream(bo);
            oo.writeObject(obj);
            bytes = bo.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                oo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }
}

4.随机存取流

    可以解决之前不能追加文件内容,只能覆盖的情况

  

  

原文地址:https://www.cnblogs.com/zhuangwei1015/p/10010058.html

时间: 2024-11-05 00:40:43

Java基础—IO小结(二)缓冲流与其它流的使用的相关文章

Java基础—IO小结(二)大纲待更新

一.缓冲流的使用 每个字节流都有对应的缓冲流: BufferedInputStream / BufferedOutputStream 构造器: 方法摘要与对应节点流类似 使用缓冲流实现文件复制:实际中也是 @Test public void testBuffered1() { // 同样需要先关联文件,注意文本使用Reader Writer,非文本使用fis fos File file1 = new File("D:\\test\\1.jpg"); File file2 = new F

Java基础——iO(二)

接着上一篇,继续做学习笔记.学IO这块,突然找到一点好处,好像以后操作电脑,尤其是电脑里的文件啥的,可以很少的用鼠标了.添加.修改.删除啥的,几行代码就可以搞定了.这只是我一个初学者的一点小心思,IO背后的大用处,相信还有很多很多.继续学习ing.... 一.缓冲流和装饰模式 缓冲流(包装类),缓冲区的出现提高了对数据读写的效率,它可以用来对流进行包装,在流的基础上对流的功能进行了增强.和底层系统提供的缓冲区有什么区别?底层直接和目标设备交换数据,包装类中,通过被包装的对象. BufferedR

Java基础—IO小结(待整理)

文件分割符:Windows中使用\ 推荐路径使用方式(反斜杠):D:\KuGou\123.jpg  (D:\\KuGou\\123.jpg) io异常的处理方式:io一定要写finally: 使用流一定要记得关闭! 创建源->选择流->操作(准备容器等)->关闭 有点类似于搬家 流的本质是数据传输一 .IO流的分类 A.根据处理数据类型的不同分为:字符流和字节流 B.根据数据流向不同分为:输入流和输出流 C.按功能分:节点流(一线的,离源最近的)和处理流 二.字节流与字符流 输入流与输出

黑马程序员——java基础---IO(input output)流字符流

黑马程序员——java基础---IO(input output)流字符流 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- io(input output)流特点: 1,io流用来处理数据之间的传输 2,java对数据的操作是通过流的方式: 3,java用于操作流的对象都在io包中: 4,流按操作数据分为两种:字节流和字符流: 5,流按流向分为:输入流和输出流. 注意:流只能操作数据,而不能操作文件. 3.IO流的常用基类: 1)字节流的抽象

黑马程序员——Java基础---io(上)

黑马程序员——Java基础---io(上) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java I/O系统负责处理程序的输入和输出,I/O类库位于java.io包中,它对各种常见的输入流和输出流进行了抽象.如果数据流中最小的数据单元是字节,那么称这种流为字节流:如果数据流

黑马程序员——Java基础---IO(下)

黑马程序员——Java基础---IO(下) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供了File类.properties类.打印流.序列流等和输入输出相关的类,它们能够帮助我们更好的处理信息.下面将对它们进行简单的介绍. 一.正

JAVA基础—泛型小结

概念: 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引入泛型的好处是安全简单. 泛型的常用字符代表意思: ? 表示不确定的java类型. T  表示java类型. K V 分别代表java键值中的Key Value. E 代表Element. 下面转载于cnblog上一个写的很好的例子 真的很好,我写了半天,当看到他这个后,立即删除~ 普通泛型

java基础知识(二)

1.关于static关键字总结: 1.不能在static修饰的方法中引用this变量,只能引用一些静态变量或方法,或new新的对象(可以定义局部变量). 简言之,静态方法或块中,只能引用静态的方法或变量. 2.类中的成员变量(static修饰)有缺省值,而类的定义的方法中的局部变量没有缺省值. 3.在类的构造器中,可以引用任何的静态或非静态的变量和方法,可以在非static方法中调用static方法. 4.static{}块中的代码在类装载中仅执行一次. 5.在7-7,A staticmetho

java基础知识回顾之javaIO类--内存操作流ByteArrayInputStream和ByteArrayOutputSteam(操作字节数组)

直接看代码: package cn.itcast.io.p6.bytestream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class ByteArrayStreamDemo { /** * @param args * @throws IOException * 特点 * 1.内存操作流 * 2.不操作底层资源,不调