zoukankan      html  css  js  c++  java
  • IO 流

    一、流的简介

    输入流:负责把硬盘中的数据读取到内存中

    输出流:负责把内存中的数据读取到硬盘中

    1字符=2字节  1字节=8位

    1.1流的分类:

    (1)字符流:读取文件中的字符,只适用于读文本文件,凡是Writer/Reader结尾的流都是字符流

    (2)字节流:读取文件中的字节,可以读取视频、图片、文本等等文件,凡是Inputstream/Outputstream结尾的流都是字节流

    1.2流的顶级父类

     

    java.io下常用的16个流:

     

     二、字节流

    2.1、一切皆为字节

    一切文本数据(视频、图片、文本)在存储时,都是以二进制数字的形式进行保存,都是一个个的字节,那么传输时一样如此。所以字节流可以传输任意的数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输始终为二进制数据。

    2.2字节输出流

    (1)成员方法

    void close() 关闭此输出流并释放与此流关联的任何系统资源,用完流要记得关闭,不占用空间。
    void write(byte[] b) 写入的时候可以和byte[]数组搭配使用,一次写入多个字符
    void write(byte[] b, int off, int len) 写 len字节指定字节数组中的偏移 off开始到输出流。
    void flush()      刷新输出流,使缓存数据被写出来。
    abstract void write(int b) 将指定的字节写入该输出流中。

    (2)构造方法摘要

    1、FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的文件输出流,传入文件所在的路径和文件名称

       FileOutputStream(String name,boolean append) 创建一个向具有指定名称的文件中写入数据的文件输出流,当boolean append为true时,

                            以追加的方式进行写入数据,默认会覆盖原文件。

       String name:目的地是一个文件路径

    2、FileOutputStream(File file)  创建一个向指定File对象表示的文件中写入数据的文件输出流,直接传入文件对象

       FileOutputStream(File file,boolean append) 创建一个向指定File对象表示的文件中写入数据的文件输出流,当boolean append为true时,

                            以追加的方式进行写入数据,默认会覆盖原文件。

      File file:目的地是一个文件

    3、FileOutputStream(FileDescriptor fdObj)  创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。

    构造方法的作用:

      1、创建一个FileOutputStream对象

      2、会根据构造方法中传递的文件/文件路径,创建一个空的文件

      3、会把FileOutputStream对象指向创建好的文件

    2.3、outputstream字节输出流-写入数据的原理(内存-->硬盘

    java程序-->JVM-->OS(操作系统)-->OS调用写数据的方法-->把数据写入到文件中

    2.3.1一次写入单个字节:

    package IO;
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Demo {
        public static void main(String[] args) throws IOException {
            //创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
            FileOutputStream fos = new FileOutputStream("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\a.txt");//会抛出文件找不到异常,用try-catch
            fos.write(97);//写进去的是二进制数据所对应的字符a
            fos.close();
    
        }
    }

    存入结果:

    package IO;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Demo {
        public static void main(String[] args) throws IOException {
            //创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
            FileOutputStream fos = new FileOutputStream(new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt"));//会抛出文件找不到异常,同try-catch
            //在文件中显示100,写个字节
            fos.write(49);
            fos.write(48);
            fos.write(48);
            //释放资源
            fos.close();
    
        }
    }

    存入结果:

    2.3.2写入多个字节:

    每次都用writer()写入一个字符,会显得特别麻烦,字节流可以和byte[]数组搭配使用,public void write(byte[] b):将b.length(数组长度个)字节从指定的字节数组写入此输出流

    一次写多个字节:

      如果写的第一个字节是正数(0--127),那么显示的时候会查询ASCII表

      如果写的第一个字节是负数(0--127),那么第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)

    
    
    package IO;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Demo {
    public static void main(String[] args) throws IOException {
    //创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
    FileOutputStream fos = new FileOutputStream(new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt"));//会抛出文件找不到异常,同try-catch
    byte[] bytes1 = {65,66,67,68,69};//ABCDEFG
    byte[] bytes2 = {-65,-66,-67,68,69};//存入的第一个字符为负数的话,则会两两组合成一个新的字符,即-65和-66,-67和68,69存入三个字符
    fos.write(bytes1);
    fos.write(bytes2);
    //释放资源
    fos.close();
    
    }
    }
    向b.txt存入:ABCDE烤紻E

    public void write(byte[] b, int off, int len) //把字节数组的一部分写入到文件中,off:数组索引起始位置,len:写入的长度

    package daily;
    
    import java.io.*;
    
    public class date5_6 {
            public static void main(String[] args) throws IOException {
                //创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
                FileOutputStream fos = new FileOutputStream(new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt"));//会抛出文件找不到异常,同try-catch
                byte[] bytes1 = {65,66,67,68,69};//ABCDEFG
                fos.write(bytes1,1,2);//索引从1开始,写入两个长度的字节即写入66和67
                //释放资源
                fos.close();
    
            }
        }
    
    
    运行结果:BC

    记事本内容:

     三、Inputstream-字节输入流,读出数据的原理(硬盘-->内存

     3.1构造方法:

    FileInputStream(File file)    通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    FileInputStream(String name)   通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
    FileInputStream(FileDescriptor fdObj)  通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。

    3.2基本方法

          int available()  返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数/获取当前流中没有读到的字节数。
                  void close() 关闭此文件输入流并释放与此流有关的所有系统资源。
            proteced void finalize()  确保在不再引用文件输入流时调用其 close 方法。
            FileChannel getChannel() 返回与此文件输入流有关的唯一 FileChannel 对象。
            FileDescriptor getFD() 返回表示到文件系统中实际文件的连接的 FileDescriptor 对象,该文件系统正被此 FileInputStream 使用。
            intread()  从此输入流中读取一个数据字节。

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

    从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
    longskip (long n) 从输入流中跳过并丢弃 n 个字节的数据。

    3.3、一次读取单个字节读取过

    public class Demo {
        public static void main(String[] args) throws IOException {
    
            FileInputStream fos = new FileInputStream(new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt"));//会抛出文件找不到异常,同try-catch
            int len = fos.read();//通过字节流读取到的字节,实际上是字节所对应的编码,是整型int
            System.out.println(len);
    
            len = fos.read();
            System.out.println(len);
    
            len = fos.read();
            System.out.println(len);
            
            len = fos.read();
            System.out.println(len);
            fos.close();
    
        }
    }

    输出结果:
    104 101 108 108

    3.4、一次读取多个字节:inputstream可以和byte[ ]数组搭配使用,加快读取速率不用一次次的读

    public class Demo {
        public static void main(String[] args) throws IOException {
            //创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
            FileInputStream fos = new FileInputStream(new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt"));//会抛出文件找不到异常,同try-catch
    //        byte[] byte2 = "hello java!".getBytes();
            byte[] bytes = new byte[2];
            int len = fos.read(bytes);//读取到并放入bytes数组中
            System.out.println(Arrays.toString(bytes));//将数组中的数据以字符串的方式打印输出
            System.out.println(new String(bytes));//byte数组中的数据转换成字符串打印输出
            //释放资源
            fos.close();
    
        }
    }

    输出结果:

    [65, 66]
    AB

     

    四、关于try{}--catch{}--finally{}和流的关系

    异常捕获try--catch--finally:

    例子:利用try--catch捕获异常形式,把a.txt中的数据复制到b.txt中

    package daily;

    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;

    public class date5_6 {
    public static void main(String[] args) throws IOException {
    //把文件a.txt中的数据写入b.txt中,实例化两个文件输入输出流
    FileReader a = null;
    FileWriter b = null;
    try{
    a = new FileReader("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\a.txt");
    b = new FileWriter("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt",true);//append:true以追加的方式在文件的末尾添加,不然每次都会重新覆盖之前所插入的
    int len=0;
    while ((len = a.read())!=-1)//读取到文件末尾为-1
    {
    b.write(len);
    }
    }catch(IOException e)
    {
    System.out.println(e);
    }finally {
    a.close();
    b.close();
    }
    } }

    五、字符流:只能操作文本文件,不能像字节流一样操作视频、声音、图片等文件

    5.1  Reader:FileReader文件字符输入流,读取文本文件当中的字符到内存中,读取过程和上面的字节流一致,可以一次读取单个字符,也可以结合char[]一次读取多个字符

    5.2 构造方法:

     FileReader(File file)  在给定从中读取数据的文本文件对象的情况下创建一个新 FileReader
     FileReader(String fileName)  在给定从中读取数据的文件名的情况下创建一个新 FileReader
     FileReader(FileDescriptor fd)  在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader

    5.3  通过FileReader文件字符输入流读取单个字符:

    package daily;
    
    import java.io.*;
    
    public class date5_6 {
            public static void main(String[] args) throws IOException, IOException {
                FileReader fos = new FileReader((new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt")));
                int i = fos.read();//通过字符流读取到的字符也是字符所对应的编码,为整型
                int j = fos.read();
                System.out.println(i);
                System.out.println(j);
                fos.close();
            }
    }
    输出:65
       66

    5.4 通过FileReader文件字符输入流读取多个字符:字符流可以和char[ ] 数组搭配使用,一次读取数组长度个大小的字符

    public class date5_6 {
            public static void main(String[] args) throws IOException, IOException {
                FileReader fos = null;
                try{
                        fos = new FileReader((new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt")));
                        int count=0;
                        char[] ch = new char[4];//一次读取四个字符
                        while((count=fos.read(ch))!= -1)//读取到末尾为-1
                        {
                            System.out.print(new String(ch,0,count)); //将读取到的字符写入ch这个字符数组中
                        }
                }catch (IOException e)
                {
                    System.out.println(e);
                }finally {
                    fos.close();
                }
            }
    }
    
    输出:我是中国人
    
    注意:这里你idea或者文本文档为gbk,请统一修改成utf-8,文本文档通过另存为可以修改

    5.5 FileWriter:FileWriter文件字符输除流,将字符从内存写入到硬盘的文本文件中,写入过程和上面的字节流一致,可以一次写入单个字符,也可以一次写入多个字符

    FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。当Boolean append为true时表示追加写入不会覆盖
    FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
    FileWriter(String fileName, boolean append) 根据给定的文件名构造一个 FileWriter 对象。当Boolean append为true时表示追加写入不会覆盖
    FileWriter(FileDescriptor fd) 构造与某个文件描述符相关联的 FileWriter 对象。

    5.6  通过FileWriter文件字符输出流写入单个字符:

    public class date5_6 {
            public static void main(String[] args) throws IOException, IOException {
                FileWriter fw = null;
                try{
                      fw = new FileWriter((new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt")),true);//true表示以追加的方式添加,不会覆盖原文件
                      fw.write("我爱世界和平!");
                }catch (IOException e)
                {
                    System.out.println(e);
                }finally {
                    fw.close();
                }
            }
    }
    
    加入结果:我是中国人我爱世界和平!

    5.7 通过FileWriter文件字符输出流结合char[ ]字符数组写入多个字符:

    package daily;
    
    import java.io.*;
    
    public class date5_6 {
            public static void main(String[] args) throws IOException, IOException {
                FileWriter fw = null;
                try{
                     fw = new FileWriter((new File("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\b.txt")),true);//true表示以追加的方式添加,不会覆盖原文件
                     char[] ch = new char[]{'我','希','望','世','界','没','有','战','争'};
                     fw.write(ch);
                }catch (IOException e)
                {
                    System.out.println(e);
                }finally {
                    fw.close();
                }
            }
    }
    
    插入结果:我是中国人我爱世界和平!我希望世界没有战争

    六、Properties集合与流的使用

    properties集合:是一个可以和流结合使用的键值映射map集合,properties集合的键-值都默认为字符串,常用的方法有store、load。

    store:负责把propertis映射集合中的数据存储到硬盘中;

    load:负责把硬盘中的数据加载到properties映射集合中;

    (1)通过store方法,把properties映射集合把数据写入指定文件中

    public class Demo {
        public static void main(String[] args) throws IOException {
            Properties properties = new Properties();
    
            properties.setProperty("哈哈","java");//存入键值对
            properties.setProperty("你好","c语言");
            properties.setProperty("哈喽","PHP");
            //负责把数据从集合中加载至硬盘中的文件
            FileWriter fileWriter = new FileWriter("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\a.txt");
            properties.store(fileWriter,"save date");
        }
    }

    运行结果:

     (2)通过load方法,把数据从文件读取到缓冲区中

    public class Demo {
        public static void main(String[] args) throws IOException {
            Properties properties = new Properties();
            //实例化一个文件字符流,并通过properties.load方法将文件内容加载至properties映射缓冲剂区;
            properties.load(new FileReader("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\a.txt"));
            //在这个属性列表中返回一组键,其中键和它的对应值是字符串,包括在默认属性列表中的不同键,如果同一个名称的一个键没有从主要属性列表中找到。
            Set<String>  set =  properties.stringPropertyNames();//返回properties集合列表中的键及其对应的值,其中该键及其对应值是字符串
    for(String s: set ) { String value = properties.getProperty(s);//获取键所对应的值 System.out.println("key="+s+" "+"value="+value); } } }

    七、缓冲流:bufferedStream

    (1)作用:(1)不用缓冲区,快递小哥取快递,为了熟悉环境,一次送一个快递

         (2)用缓冲区,快递小哥取快递,一次送五个快递,节省时间与效率

         (3)取代刚才的byte[ ]数组和char[ ]字符数组,达到一次性操作多个字符,提高了内存和硬盘的访问效率

    (2)分类:bufferedInputStream--字节缓冲输入流、bufferedOutputStrea--字节缓冲输出流

         bufferedWriter--字符缓冲输入流、bufferedReader--字符缓冲输出流

    (3)通过字节缓冲输入流BufferInputStream,向缓冲区以字节的形式向文件读取数据:

    public class Demo {
        public static void main(String[] args) throws IOException {
            //1.创建一个FileInputstream对象
            FileInputStream fis = new FileInputStream("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\a.txt");
            //2.创建BufferInputStream对象,对象的构造方法中传递FileInputStream对象,提高对象的利用率
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] bytes = new byte[50];
            //3.使用BufferedInputStream 的read方法将数据写入缓冲区中;
            int len=0;
            while ((len=bis.read(bytes))!=-1)
            {
                System.out.print(new String(bytes));
            }
            //4.使用BufferInputSteam 对象中的flush方法将缓冲区的数据刷新到文件中;
    
        }

    (4)使用buffered缓冲流和不适用缓冲流的读取速度时间比较:当文本中的数据比较小时差距可能不是很明显

    public class Demo {
        public static void main(String[] args) throws IOException {
            Long s = System.currentTimeMillis();
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\Users\ibear\Documents\WeChat Files\xwnaxcm\a.txt"));
            byte[] bytes = new byte[10];
            int len = 0;
            while ((len = bis.read(bytes)) != -1) 
            {
                System.out.println(new String(bytes));
            }
            Long e = System.currentTimeMillis();
            Long c = e - s;
            System.out.print("本次使用缓冲流读取时间:" + c + "毫秒");
        }
    }

    运行结果:
    本次使用缓冲流读取时间:18毫秒


    package daily;
    
    import java.io.*;
    
    public class date5_6 {
            public static void main(String[] args) throws IOException {
                Long s = System.currentTimeMillis();
                FileInputStream bis = new FileInputStream("C:\Users\ibear\Desktop\单词.txt");
                byte[] bytes = new byte[10];
                int len = 0;
                while ((len = bis.read(bytes)) != -1)
                {
                    System.out.println(new String(bytes));
                }
                Long e = System.currentTimeMillis();
                Long c = e - s;
                System.out.print("本次未使用缓冲流读取时间:" + c + "毫秒");
            }
        }
    运行结果:本次未使用缓冲流读取时间:23毫秒
        }
  • 相关阅读:
    asp.net(C#)页面事件顺序
    C#多线程学习 之 线程池[ThreadPool]
    JS 获取浏览器窗口大小
    关于Json的那点事
    jquery 动态滚动
    Null,DBNull,String.Empty 区别 C# 转载
    js图片大小限制,设置
    mysql 自定义函数获取两点间距离
    KindleConverter:Word批量转换为6寸PDF
    在 Asp.NET MVC 中使用 SignalR 实现推送功能
  • 原文地址:https://www.cnblogs.com/ibear/p/12545865.html
Copyright © 2011-2022 走看看