• I/O流——字节流


    流的概念

    流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以使文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

    流的分类

    ①   流按其流向分为“输入流”和“输出流”。

    ②   流按数据传输单位分为“字节流”和“字符流”。

    a)         “字节流”用来读写8位二进制的字节。

    b)         “字符流”用来读写16位二进制字符。

    ③   流按功能分为“节点流”和“过滤流”。

    a)         “节点流”用于直接操作目标设备的流。例如:磁盘或一块内存区域。

    b)         “过滤流”是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

     

    字节流

    字节流类用于向字节流读取8位二进制的字节。一般地,字节流主要用于读写诸如图像或声音等二进制数据。

    字节流类以InputStream和OutputStream为顶层类。它们都是抽象类。

    一、InputStream

    ①     InputStream是定义了字节输入流的抽象类。

    ②     InputStream中定义的方法

    a)         public abstract int read()

    b)         public int read(byte[] b)

    c)         public int read(byte[] b,int off,int len)

    d)         public long skip(long n)

    e)         public int available()

    f)          public void close()

    二、OutputStream

    ① OutputStream是定义了字节输出流的抽象类。

    ② 该类所有方法返回void值,在出错情况下抛IOException异常

    ③ OutputStream中定义的方法

    g)         public abstract void write(int b)

    h)         public void write(byte[] b)

    i)           public void write(byte[] b,int off,int len)

    j)           public void flush()

    k)         public void close()

    每个抽象类都有多个具体的子类,这些子类对不同的外设进行处理,例如磁盘文件,网络连接,甚至是内存缓冲区。

    三、FileInputStream

    ① FileInputStream类表示能从文件读取字节的InputStream类

    ② 构造方法

    a)         FileInputStream(String filePath)

    b)         FileInputStream(File fileObj)

    四、FileOutputStream

    ① FileOutputStream表示能向文件写入字节的OutputStream类

    ② 构造方法

    a)         FileOutputStream(String filePath)

    b)         FileOutputStream(File fileObj)

    c)         FileOutputStream(String filePath,boolean append)

    示例:拷贝指定文件到指定目录

     1 class FileCopyUtil {
     2     public static void copyFile(File src, File dst) throws IOException {
     3         FileInputStream fis = new FileInputStream(src);
     4         FileOutputStream fos = new FileOutputStream(dst);
     5         long time1 = System.currentTimeMillis();
     6         int data = -1;
     7         while ((data = fis.read()) != -1) {
     8             fos.write(data);
     9         }
    10         fis.close();
    11         fos.close();
    12         long time2 = System.currentTimeMillis();
    13         System.out.println("复制完成,共花费:" + (time2 - time1) + "毫秒");
    14     }
    15 }

    主方法:

    1         try {
    2             FileCopyUtil.copyFile(new File("d:/zhangsan/tu.png"), new File("e:/fuzhi.png"));
    3         } catch (IOException e) {
    4             e.printStackTrace();
    5         }

    输出结果

    复制完成,共花费:1545毫秒

    单一张71K的图片就花费了1545毫秒,由此可见效率是极低的,因为它是读一个写一个,我们可以换种思路,先全部读到一个缓冲区,再将内容一次性写入。这里就好比喝水时一滴一滴地喝还是接到杯子里再喝。

    改造下方法,如下:

     1 class FileCopyUtil {
     2     public static void copyFile(File src, File dst) throws IOException {
     3         FileInputStream fis = new FileInputStream(src);
     4         FileOutputStream fos = new FileOutputStream(dst);
     5         byte[] buff = new byte[1024 * 1024];// 创建一个1M大小的缓冲区,用来存放输入流中的字节
     6         int len = 0;// 用来保存实际读到的字节数
     7         long time1 = System.currentTimeMillis();
     8         while ((len = fis.read(buff)) != -1) {
     9             fos.write(buff, 0, len);
    10         }
    11         fis.close();
    12         fos.close();
    13         long time2 = System.currentTimeMillis();
    14         System.out.println("复制完成,共花费:" + (time2 - time1) + "毫秒");
    15     }
    16 }

    同样读取那张图片,输出结果:

    复制完成,共花费:3毫秒

    再复制一个8M的mp3格式文件,输出结果:

    复制完成,共花费:39毫秒

    五、ByteArrayInputStream

    ①ByteArrayInputStream是把字节数组当成源的输入流。

    ②两个构造方法,每个都需要一个字节数组提供数据源:

    a)       ByteArrayInputStream(byte array[])

    b)       ByteArrayInputStream(byte array[],int start,int numBytes)

    1         String str="hello,HangZhou";
    2         ByteArrayInputStream bis=new ByteArrayInputStream(str.getBytes());
    3         int data=-1;
    4         while((data=bis.read())!=-1)
    5         {
    6             System.out.println((char)data);
    7         }

    输出结果:

    h e l l o , H a n g Z h o u

    六、ByteArrayOutputStream

    ①ByteArrayOutputStream是把字节数组当作目标的输出流。

    ②两个构造方法:

    a)       ByteArrayOutputStream()

    创建一个新的byte数组输出流

    b)       ByteArrayOutputStream(int numBytes)

    创建一个新的byte数组输出流,具有指定大小缓冲区(字节为单位)

     1         ByteArrayOutputStream bos = new ByteArrayOutputStream();
     2         bos.write(97);
     3         bos.write(65);
     4         try {
     5             bos.write("hello,word".getBytes());
     6         } catch (IOException e) {
     7             e.printStackTrace();
     8         }
     9         byte[] buff = bos.toByteArray();
    10         for (byte b : buff) {
    11             System.out.print((char)data+" ");
    12         }
    13 
    14         FileOutputStream fos=new FileOutputStream("d://aa.txt", true);
    15         bos.writeTo(fos);//把ByteArrayOutputStream内部缓冲区的数据写到对应的文件输出流中
    16         fos.close();

    输出结果:

    aAhello,word

    并会在d盘下创建一个aa.txt文件,里面内容为输出结果的内容,再次执行将追加一次执行结果的内容。

    过滤流

    ① 过滤流仅仅是为底层透明地提供扩展功能的输入流(输出流)的包装。这些流一般由普通类的方法(即过滤流的一个父类)访问。

    ② 过滤字节流FilterInputStream和FilterOutputStream。构造方法:

    a)  FilterInputStream(InputStream is)

    b)  FilterOutputStream(OutputStream os)

    ③ 这些类提供的方法和InputStream及OutputStream类的方法相同。

    ④ 常用的过滤流BufferedInputStream和BufferedOutputStream,DataInputStream和DataOutputStream

     

    BufferedInputStream,BufferedOutputStream用法举例

    使用过滤流来改写上面的复制方法

     1 class FileUtil {
     2     public static void copyFile(File src, File dst) throws IOException {
     3         FileInputStream fis = new FileInputStream(src);
     4         FileOutputStream fos = new FileOutputStream(dst);
     5         BufferedInputStream bis=new BufferedInputStream(fis);
     6         BufferedOutputStream bos=new BufferedOutputStream(fos);
     7         
     8         int data = 0;// 用来保存实际读到的字节数
     9         long time1 = System.currentTimeMillis();
    10         while ((data = bis.read()) != -1) {
    11             bos.write(data);
    12         }
    13         bis.close();
    14         bos.close();
    15         long time2 = System.currentTimeMillis();
    16         System.out.println("复制完成,共花费:" + (time2 - time1) + "毫秒");
    17     }
    18 }

    主方法:

    1         try {
    2             FileUtil.copyFile(new File("d:/zhangsan/Closer To Me.mp3"), new File(
    3                     "e:/fuzhi.mp3"));
    4         } catch (IOException e) {
    5             e.printStackTrace();
    6         }
    7     }

    复制同样的一首歌,输出结果:

    复制完成,共花费:905毫秒

    时间增加了很多,但也比文件直接读写快了不少。Buffered中自带一个8k左右的缓冲区。

    DataInputStream和DataOutputStream用法举例:

    写入文件:

     1         String name="zhangsan";
     2         int age=10;
     3         boolean flag=true;
     4         char sex='男';
     5         double money=123.45;
     6         
     7         DataOutputStream dos=new DataOutputStream(new FileOutputStream("d:/b.txt"));
     8         dos.writeUTF(name);
     9         dos.writeInt(age);
    10         dos.writeBoolean(flag);
    11         dos.writeChar(sex);
    12         dos.writeDouble(money);
    13         dos.close();

    打开b.txt后发现有乱码,那是因为写进去的是二进制

    读文件:

    1         DataInputStream dis=new DataInputStream(new FileInputStream("d:/b.txt"));
    2         //读的顺序必须与写入的顺序一致
    3         System.out.println(dis.readUTF());
    4         System.out.println(dis.readInt());
    5         System.out.println(dis.readBoolean());
    6         System.out.println(dis.readChar());
    7         System.out.println(dis.readDouble());
    8         dis.close();

    输出结果:

    zhangsan

    10

    true

    123.45

    过滤流总结:

    BufferedInputStream与BufferedOutputStream

    需要使用已经存在的节点流来构造,提供缓冲的读写,提高了读写的效率。

    DataInputStream与DataOutputStream

    数据输入输出流允许应用程序读写基本Java数据类型。应用程序可以使用数据输出流写入,稍后由数据输入流读取。读写顺序要保持一致。

  • 相关阅读:
    轮廓 | outline (Basic User Interface)
    转换 | CSS Transitions (Animations & Transitions)
    越线 | line-break (Text)
    贴士和技巧 | CSS Animations: Tips (Animations & Transitions)
    负 | @counter-style.negative (Counter Styles)
    调整 | resize (Basic User Interface)
    再见乱码:5分钟读懂MySQL字符集设置
    git
    Python 内存&函数调用关系图
    Python 笔记
  • 原文地址:https://www.cnblogs.com/wzy330782/p/5471515.html
Copyright © 2020-2023  润新知