java之旅 (第十二天) IO流

InputStream:(字节流)
    public abstract class InputStream:该抽象类是所有的类    表示字节输入流的父类
    
    构造:
    //FileInputStream(String name):通过字符串找路径(隐含    着创建了一个File对象)
        InputStream fis = new FileInputStream("b.txt");
    注:直接就把文件的绝对路径写下去就行,直接创建流对象

    读取数据:
    1.int read():从此输入流中读取一个数据字节。
    举例:
    while(( by = fis.read()) != -1) {
    System.out.print((char)by); //因为返回的是            一个字节数的整数,所以我们需要转换成字符 变            成我们看的懂的东东西
        }
    注:
    1.字节流把数据转码为字节数,编码后存储起来。因此返回    的是byte类型数据,我们需要转化为char类型(码表)
    2.read()一次读取一个字节的数据,如果没有读取到就返    回-1
    3.记得关闭流 .close()
    4.目前只能读取英文字母(AScll码内),不能读取中文

     2.int read(byte[] b):一次读取一个字节数组 
        //创建输入流
        InputStream fis = new                              FileInputStream("b.txt");

        //String(byte[] value, int offset, int count)
        //根据指定数组,提取其内容返回一个新的String类型        的数据,从指定位置开始到指定位置的读取
        System.out.println(new String(bys,0,len));
        此句话把输出的内容转化为字符串
    
        byte[] bys = new byte[1024]; //通常默认为 1024
        int len = 0; //计算长度,并做为循环条件
        while((len = fis.read(bys)) != -1) {
            System.out.println(new                            String(bys,0,len));//一次读取1024个字节,如果没                                    有就返回-1,
        }
        注:
        在写入数据时,最好把范围规定在[0,len],以防写入        过多的空格


OutputStream:(字节流)    
    这个OutputStream是一个抽象类,我们不能实例  根据抽象    类如何实例 我们之前学过,使用多态的方式
    所以我们需要找他的子类:FileOutputStream

    1.eOutputStream的构造方法:
    FileOutputStream(File file): 创建一个向指定 File 对象    表示的文件中写入数据的文件输出流。
    FileOutputStream(String name):创建一个向具有指定名称    的文件中写入数据的输出文件流。
    注:
    io流负责输入输出,但是依附于文件,因此需要找到那个    文    件才能进行输入输出吧,因此需要创建一个文件对象(File     对象)。可以显性创建一个File对象,也可以直接用字符    串,源码会帮我们在自动创建一个File对象

    字节流输出的步骤:
         a.创建输出流
         b.写出数据
         c.资源释放(一定要记得)  //.close()避免很多问题

        /方式一
        //        File file = new File("demo.txt");
        //        OutputStream fos = new     fileOutputStream(file);

        //方式二
        //        OutputStream fos = new     fleOutputStream(new File("a.txt"));
            关闭流
        /*
             所有的流一定要记得关闭
             否则这个流会在内存中占用空间
             关闭流其实不是立即关闭,只是通知系统这个资            被释放。
             可以在合适的时候去进行回收
         */
        //        fos.close();

2.写入数据
    void write(byte[] b):写一个字节数组的数据 
     void write(byte[] b, int off, int len):写一个字节数组    的数据,从指定位置开始到指定位置结束
     void write(int b):写一个int类型的数据
    举例:
    FileOutputStream fos = new     FileOutputStream("a.txt");
        //        fos.write(97);//二进制 -- 转码 -- 找                            到97对应的字符(a),而不                            是97的整数
        //        fos.write(98);

        byte[] bys = {97,98,99,100,101,102,103};
        fos.write(bys);
        fos.write(bys, 1, 4);//bcde
        fos.close();
    
    注:
    1. 如果我们需要使用输出流进行换行的操作,你直接写           println是无效的,因为这个跟写出本质上是没有关系
       所以,我们可以使用\n的转义字符明确的告知需要进行换       行但是,我们用过高级记事本发现确实换行了,但是记事       本确没有进行换行针对这个问题,我们需要了解一些。
       每一个操作系统对于转义字符的识别是不一致的,而大多       高级记事本是能够自己进行转义和识别
       Windows:\r\n
       linux:\n
       Mac os:\n
     而Windows自带的记事本是基于Windows平台来写的,所以他     只能够识别\r\n是换行的意思
    
    举例:
    OutputStream fos = new FileOutputStream("b.txt");
        for (int i = 1; i < 6; i++) {
            fos.write(("toobug"+i+"\r\n").getBytes());
                            //字符串转为一般数组

    //参数如果有true,就代表写入位置为文件末尾处开始,而不是文件开始处(追加的写法)
        OutputStream fos2 = new     FileOutputStream("b.txt",true); //是在创建io流对象时                                写true
        for (int i = 1; i < 6; i++) {
            fos2.write(("java"+i+"\r\n").getBytes());
            //必须转化为字节才能进行写入
            //fos.write("\n".getBytes());
        } 

    ileInputStream fis = new FileInputStream("F:\\seehope_edu\\Java_20180420\\javase_day16\\课堂笔记\\img\\1.png");
        FileOutputStream fos = new FileOutputStream("F:\\seehope_edu\\Java_20180420\\javase_day16\\课堂笔记\\img\\2.png");
        
        int by = 0;
        while((by = fis.read())!=-1) {
            fos.write(by);
        }  //读一个 写一个 避免多出 少了 一个字节(很                                               慢)

    byte[] bys = new byte[2048];
        
        int len = 0;//计数,并做循环条件
        while((len = fis.read(bys))!= -1) {//28 = -1
            fos.write(bys);//2048(有数据) 0  - 28
        }
        long e = System.currentTimeMillis();
        System.out.println("共计:"+(e-s)+"毫秒");
    注:
    1.如果字符数组长度不够,len返回数组最大数;
    如果字符数组够长,返回实际装载数据的长度;
    最后一次肯定是获取不到字符(结尾)返回1
    实际长度: 帮助写入数据    -1: 循环条件
    2.如果是用数组读取,系统会开一个缓冲区,并一次读取    1024个字节数,速度很快(基本去到300多兆每秒,下一个真    正的缓冲区更快,可以去到400多兆,跟固态有的一拼,不会    超过固态,不可能超过最大物理性能,不然无法进行写入写    出了)
    

buffered_IO:(带缓冲区的字节流)
    我们上午通过创建一个数组的方式来读取数据确实比之前一    个字节一个字节的读,效率很明显要快很多。
    既然,带上缓存区的数据读取效率这么高,那么在Java设计    之初,其实已经为我们设计了一个带缓冲区的输入和输出流
    这种类也就是我们俗称的:缓冲区流
    缓冲区输入流:BufferedInputStream
    缓冲区输出流:BufferedOutputSteam
    注:
    之前的创建数组是模拟缓冲区,而这个是正统的缓冲区

    BufferedOutputSteam构造方法:
    BufferedOutputStream(OutputStream out):创建一个缓冲区                                    输出流
     BufferedOutputStream(OutputStream out, int size):创建    一个缓冲区输出流,并且指定缓冲区大小(一般不用,有默认    的缓冲区)
    注:
    1.BufferedOutputStream不是虚类,可以直接new一个对象
    2.BufferedOutputStream没有具体功能,只是开一个缓冲    区,具体功能只能通过FileOutputStream对象来实现
    3.OutStream不能创建对象, 必须用FileOutputStream
    4.OutStream是所有输入类的父类(多态)
    5.输出时记得要.flush()刷新,然后再推出

    Test:
     四种流的对比: 
     要求,将一个大小为41M的视频进行拷贝来对比速度
     method01(一个个读):基本的字节流 耗时:2分钟左右
     method2(开数组);带数组的字节流 耗时:0.3秒
     method03(一个个读):字节缓冲区流的字节读取 1.5秒
     method04():带数组的缓冲区字节流:0.1秒

    
InputStreamReader:
    字节流,无论是输出,输入都只能以字节的方式。现在介绍    一种以字符形式输出,输入的方式(只是字符转换流)

    字节流读取中文出现的问题
    while((by = fis.read())!=-1) {
            //????¤?????¤??°??????????
            System.out.print((char)by);
        }*/
        
        byte [] bys = new byte[1024];
        int len = 0;
        while ((len = fis.read(bys))!= -1) {
            //浠婂ぉ鐨勫ぉ姘旂壒鍒ソ
            System.out.println(new String(bys,0,len,"utf-8"));
            
        }
    //读取笔记本的中文时,输出一堆看不懂的
    
    InputStreamReader(InputStream in):使用默认的字符集编    码来进行内容的读取
     InputStreamReader(InputStream in, Charset cs):使用指    定的字符集编码进行内容读取
    
    1.eclipse默认的是GBK格式,记事本的不一定,不同要转
    3.InputStreamReader不是虚类,可以new自己
    4.InputStreamReader也只是提供解码的方法,具体输入输出    还是需要FileOutputStream来完成,而FileOutputStream又    需要File对象来找到指定的文件。(一级套一级)
    5.InputStreamReader只是以字符来读取,但是read返回的是    int类型(某种编码,用char转换后可输出。如果是同一种编    码格式,会输出我们想要的,如果不是就会输出不同)
    6.只是针对文字,如果是字母,都一样,不存在编码转换
    7.在输入流内,解码类型一定要与java文件的默认类型相    同,因为是想要输入到我们的程序中
    注:
    UTF-8 格式 可以兼容任何格式,但是eclipse默认为    “GBK”,GBK不能解码UTF-8,因此在输入流中,要以编译器    为准,这样子编译器才知道进来的是什么。当然如果文本文    件是UTF-8就会出错,因此要把文件转为ANSI就不会有错

    字符转换流:
        OutputStreamWriter:
        void write(char[] cbuf, int off, int len):写入字        符数组的某一部分。 
        void write(int c):写入单个字符。 
        void write(String str, int off, int len):写入一        个字符串的一部分
    
    举例:
        OutputStreamWriter osw = new                  OutputStreamWriter(new FileOutputStream("b.txt"));
        osw.write(97);//自动转为字符
        osw.write('a');
        osw.flush();//刷新流,可能写入的数据不会被及时    刷新,所以不会有显示 一般在写入数据之后,记得刷新
        char [] ch = {'h','a','b'};
        osw.write(ch);
        osw.flush();
        osw.write("我爱橘梨纱");
        osw.flush();
        osw.close();
注:
    与字节流不同的是,它可以直接写入字符与字符串,而字节    流必须写入byte类型,然后它才会去找表把其变为字符
    
    String(byte[] bytes, String charsetName):通过制定的字    符集编码解码字节数组
    byte[] getBytes(String charsetName):使用指定的字符集    编码生成字节数组

    编码:把看的懂的文字变成乱码形式(看不懂的)
        String -- byte[]
    解码:看不懂的东西解码成看的东西
        byte[] -- String
    
    在解码的过程当中,一定要注意一个问题,就是两个码的字    符集编码平台是否能够兼容,
    如果不能够兼容就需要手动来声明解码的平台应该是哪一种

    String s = "龙哥";
        byte [] bys = s.getBytes();
        //编码的过程
        System.out.println(Arrays.toString(bys));


        //解码的过程
        //        String str = new String(bys);
        String str = new String(bys,"GBK");
        System.out.println(str);
        注:
        字符串最后变为二进制存储起来

    BufferedReader br = new BufferedReader(new FileReader("InputStreamDemo01.java"));
        //int read() 读取单个字符
        //        int a = br.read();
        //        System.out.println(a);

        //br.readLine(); 读取一整行
        //        String line = br.readLine();
        //        System.out.println(line);

        String line = null;
        //        while ((line = br.readLine())!= null) {
        //            System.out.println(line);
        //        }


        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        while ((line = br.readLine())!= null) {

            bw.write(line);//写入数据
            bw.newLine();//执行新行
            bw.flush();//刷新缓冲区
        }


    总结:
    1.IO流分类:
        流向:
            输出流:写出数据
            输入流:读取数据
        类型:
            字节:
                输出流:写出数据 OutputStream
                输入流:读取数据 InputStream
            字符:
                输出流:写出数据 Writer
                输入流:读取数据 Reader

    2.看不懂的(图片,视频)就用字节流
      看得懂的(文本文件,中文,英文)就用字符流
    
    3.转义字符:不是真的字符,是一个功能

    4.要养成关闭流的习惯(.close()),先创建的后关闭
       如果是输出流要养成.flush(更新的习惯)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值