毕向东Java视频学习笔记【day21-IO流<1>】

01-IO流(输入流&输出流)

输入流和输出流相对于内存设备而言.

将外设中的数据读取到内存中:输入
将内存的数写入到外设中:输出。


02-IO流(字节流&字符流)

字符流的由来:

其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。
在对这个文字进行操作。简单说:字节流+编码表

字节流的两个顶层父类:
1,InputStream 2,OutputStream.

字符流的两个顶层父类:
1,Reader 2,Writer

这些体系的子类都以父类名作为后缀。
而且子类名的前缀就是该对象的功能。


03-IO流(字符流-FileWriter)


    package cn.itcast.p2.io.filewriter;
    import java.io.FileWriter;
    import java.io.IOException;
    //需求:将一些文字存储到硬盘一个文件中。   
    public class FileWriterDemo {

    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    public static void main(String[] args) throws IOException {
        //创建一个可以往文件中写入字符数据的字符输出流对象。
        /*
         * 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)。
         * 
         * 如果文件不存在,则会自动创建。
         * 如果文件存在,则会被覆盖。
         * 
         * 如果构造函数中加入true,可以实现对文件进行续写!
         */
         FileWriter fw = new FileWriter("demo.txt",true);
         /*
         * 调用Writer对象中的write(string)方法,写入数据。 
         * 
         * 其实数据写入到临时存储缓冲区中。
         * 
         */
         fw.write("abcde"+LINE_SEPARATOR+"hahaha");

         /*
         * 进行刷新,将数据直接写到目的地中。
         */
         fw.flush();
         /*
         * 关闭流,关闭资源。在关闭前会先调用flush刷新缓冲中的数据到目的地。
         */
        fw.close();
    }
}
  • FileWriter.write();

    • 写入流中(内存中),但是没保存到硬盘上
  • FileWriter.flush();

    • 刷新,保存到硬盘上
    • 相当于写文档时的ctrl+s
  • FileWriter.close();

    • 关闭流
    • 会自动调用flush,再关闭。
    • 在关闭后,无法在使用flush和write。
    • 相当于关闭一个txt文件,就无法再保存和写入了。

-

04-IO流(字符流-FileWriter-细节(换行和续写))

换行
  • fw.write(“abcde”+LINE_SEPARATOR+”hahaha”);
  • fw.write(“abcde\r\nhahaha”);//windows中换行是\r\n
续写,只用在new对象时,增加一个true参数,默认是false
FileReader fr = new FileReader("d:\\demo.txt",true);

05-IO流(字符流-FileWriter-IO异常处理)

  • if (fw != null) 一定要记住这一步
package day20;

import java.io.FileWriter;
import java.io.IOException;

public class IOExceptionDemo {

    private static final String LINE_SEPARATOR = System
            .getProperty("line.separator");

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) {

        FileWriter fw = null;

        try {
            fw = new FileWriter("d:\\demo.txt");

            fw.write("abcde" + LINE_SEPARATOR + "hahaha");

        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            if (fw != null) {//一定要记住这一步
                try {
                    fw.close();
                } catch (IOException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                    throw new RuntimeException("关闭失败");
                }
            }
        }
    }
}

06-IO流(字符流-FileReader-读取方式一)

  • FileReader.read()

    • 第一次调用只读取第1个字符的二进制
    • 第二次调用就读取下一个字符
    • 如果读到文件结尾,返回-1
  • 一般这样写来读取文件中的内容

            while((ch=fr.read())!=-1){
            System.out.println((char)ch);
            }

07-IO流(字符流-FileReader-读取方式二)

  • System.out.println(new String(buf,0,len));
    • 输出buf字符数组中从0到len-1的字符

一般buf字符数组的长度为1024的倍数

char[] buf = new char[3];

  • FileReader.read(buf)读取3个字符到buf字符数组中。
    • int num = read(buf)
      • 能返回读取字符的长度,如果只有2个字符,buf数组长度为3,返回长度2赋给num.
      • 如果1个都读取不到,返回0,并且buf为空
        列表内容
  • 一般这样写

    while((len=fr.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
    }
    

08-IO流(字符流–复制文本文件_1)

package day21;

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

/*
 * 需求:将c盘的一个文本文件复制到d盘。
 * 
 * 思路:
 * 1,需要读取源,
 * 2,将读到的源数据写入到目的地。
 * 3,既然是操作文本数据,使用字符流。 
 * 
 */

public class CopyTextTest {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {

        //1,读取一个已有的文本文件,使用字符读取流和文件相关联。
        FileReader fr = new FileReader("d:\\Demo.txt");
        //2,创建一个目的,用于存储读到数据。
        FileWriter fw = new FileWriter("d:\\copytext_1.txt");
        //3,频繁的读写操作。
        int ch = 0;
        while((ch=fr.read())!=-1){
            fw.write(ch);
        }
        //4,关闭流资源。 

        fw.close();
        fr.close();
    }

}

09-IO流(字符流–复制文本文件_2)

package day21;

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

public class CopyTextTest_2 {

    private static final int BUFFER_SIZE = 1024;

    /**
     * @param args
     */
    public static void main(String[] args) {

        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("d:\\Demo.txt");
            fw = new FileWriter("d:\\copytest_2.txt");

            //创建一个临时容器,用于缓存读取到的字符。
            char[] buf = new char[BUFFER_SIZE];//这就是缓冲区。 

            //定义一个变量记录读取到的字符数,(其实就是往数组里装的字符个数 )
            int len = 0;

            while((len=fr.read(buf))!=-1){
                fw.write(buf, 0, len);
            }

        } catch (Exception e) {
            throw new RuntimeException("读写失败");
        }finally{
            if(fw!=null)
                try {
                    fw.close();
                } catch (IOException e) {

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

                    e.printStackTrace();
                }
        }
    }

}

10-IO流(字符流-练习-复制文本文件_图解)

波浪线–流
两个流之间没有必然的联系
是通过一个媒介将其联系在一起

这个媒介其实就是缓冲区

这里写图片描述

11-IO流(字符流-缓冲区-解释)

设计优化-重构

加入设计模式,提升灵活性、复用性

性能优化

缓冲区的使用,高效性能


12-IO流(字符流-缓冲区-BufferedWriter)

缓冲区是提高效率神器
  • BufferWriter其实封装了数组 用数组来缓冲
    • FileWriter fw = new FileWriter(“buf.txt”);
    • new对象时,必须有缓冲的对象“buf.txt”
import java.io.*;
public class BufferedWriterDemo {
    @SuppressWarnings("unused")
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("buf.txt");
        //为了提高写入的效率。使用了字符流的缓冲区。
        //创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
        BufferedWriter bufw = new BufferedWriter(fw);

        //使用缓冲区的写入方法将数据先写入到缓冲区中。
        bufw.write("asdasd");
        //关闭缓冲区。其实关闭的就是被缓冲的流对象。
        bufw.close();
    }
}
关闭缓冲区的流对象,流对象不存在了,就不用再关闭fw的流对象(fw.close)。
  • buwf.newLine();
    • 换行
    • 注意:但是只有BufferWriter中有。
养成习惯刷新flush保存的习惯(ctrl+s)
        for(int x=1; x<=4; x++){
            bufw.write("abcdef"+x);
            bufw.newLine();
            bufw.flush();
        }

13-IO流(字符流-缓冲区-BufferedReader)

  • BufferedReader.readLine:string
    • 读取文件中的行 行以回车为准(\r\n)
    • 如果行中无内容,String返回null
    while((line=bufr.readLine())!=null){
        System.out.println(line);
    }

14-IO流(字符流-缓冲区-BufferedReader-readLine方法原理)

BufferedReader:StringBuilder

readLine()使用了读取缓冲区的read方法,(不读取\n换行、\r回车)将读取到的字符进行缓冲并且进行判断换行标记,将标记前的缓存数据变成字符串返回。


15-IO流(字符流-缓冲区-复制文本文件)

用bufferReader和bufferWriter复制文本文件

import java.io.*;
public class CopyTextByBufTest {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("buf.txt");      
        BufferedReader bufr = new BufferedReader(fr);

        FileWriter fw = new FileWriter("buf_copy.txt");
        BufferedWriter bufw = new BufferedWriter(fw);

        String line = null;

        //读取一行换行
        while((line=bufr.readLine())!=null){
            bufw.write(line);
            bufw.newLine();
            bufw.flush();
        }
        /*
        int ch = 0;
        while((ch=bufr.read())!=-1){
            bufw.write(ch);
        }
        */
        bufw.close();
        bufr.close();
    }
}

16、17-IO流(字符流-缓冲区-自定义MyBufferedReader-read和readLine方法)

自定义的读取缓冲区。其实就是模拟一个BufferedReader.

分析:
缓冲区中无非就是封装了一个数组,
并对外提供了更多的方法对数组进行访问。
其实这些方法最终操作的都是数组的角标。

缓冲的原理:
其实就是从源中获取一批数据装进缓冲区中。
在从缓冲区中不断的取出一个一个数据。

在此次取完后,在从源中继续取一批数据进缓冲区。
当源中的数据取光时,用-1作为结束标记。

package day21.cn.itcast.p4.io.charstream.mybuffer;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class MyBufferedReader extends Reader {
    private Reader r;
    //定义一个数组作为缓冲区。
    private char[] buf = new char[1024];
    //定义一个指针用于操作这个数组中的元素。当操作到最后一个元素后,指针应该归零。    
    private int pos = 0;    
    //定义一个计数器用于记录缓冲区中的数据个数。 当该数据减到0,就从源中继续获取数据到缓冲区中。
    private int count = 0;
    MyBufferedReader(Reader r){
        this.r = r;
    }
    public int myRead() throws IOException{
        //1,从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。
        if(count==0){
            count = r.read(buf);
            pos = 0;
        }
        if(count<0)
            return -1;
        char ch = buf[pos++];
        count--;
        return ch;
    }
    public String myReadLine() throws IOException{
        StringBuilder sb = new StringBuilder();
        int ch = 0;
        while((ch = myRead())!=-1){
            if(ch=='\r')
                continue;
            if(ch=='\n')
                return sb.toString();
            //将从缓冲区中读到的字符,存储到缓存行数据的缓冲区中。
            sb.append((char)ch);
        }       
        if(sb.length()!=0)
            return sb.toString();
        return null;
    }
    public void myClose() throws IOException {
        r.close();
    }
}

18-IO流(字符流-缓冲区-装饰设计模式)

  • 装饰设计模式:
    • 对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。
public class PersonDemo {
    public static void main(String[] args) {
        Person p = new Person();
        NewPerson p1 = new NewPerson(p);
        p1.chifan();
        NewPerson2 p2 = new NewPerson2();
        p2.chifan();
    }
}
class Person{
    void chifan(){
        System.out.println("吃饭");
    }
}
//这个类的出现是为了增强Person而出现的。
class NewPerson{//装饰模式
    private Person p ;
    NewPerson(Person p){
        this.p = p;
    }
    public void chifan(){
        System.out.println("开胃酒");
        p.chifan();
        System.out.println("甜点");
    }
}
class NewPerson2 extends Person{//继承
    public void chifan(){
        System.out.println("开胃酒");
        super.chifan();
        System.out.println("甜点");
    }
}

19-IO流(字符流-缓冲区-装饰设计模式和继承的区别)

装饰和继承都能实现一样的特点:进行功能的扩展增强。

有什么区别呢?

首先有一个继承体系。
Writer
|–TextWriter:用于操作文本
|–MediaWriter:用于操作媒体。

想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。
效率提高需要加入缓冲技术。

Writer
    |--TextWriter:用于操作文本
        |--BufferTextWriter:加入了缓冲技术的操作文本的对象。
    |--MediaWriter:用于操作媒体。
        |--BufferMediaWriter:

如果这个体系进行功能扩展,又多了流对象。
那么这个流要提高效率,是不是也要产生子类呢?是。这时就会发现只为提高功能,进行的继承,
导致继承体系越来越臃肿。不够灵活。


重新思考这个问题?用装饰模式

既然加入的都是同一种技术–缓冲。
前一种是让缓冲和具体的对象相结合。
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。

class Buffer{
    Buffer(TextWriter w)
    {}
    Buffer(MediaWirter w)
    {}
}
class BufferWriter extends Writer{
    BufferWriter(Writer w)
    {}
}

装饰也可用继承的表达方式。

    Writer
        |--TextWriter:用于操作文本
        |--MediaWriter:用于操作媒体。
        |--BufferWriter:用于提高效率。

装饰比继承灵活。

特点:装饰类和被装饰类都必须所属同一个接口或者父类。


20-IO流(字符流-缓冲区-LineNumberReader)

  • LineNumberReader 方法
    • 设置行号

21-IO流(字节流-操作文件基本演示)

字节流是不需要临时存储缓冲的,是直接写入目的地中,所以不需要flush方法,但是close方法还是需要的(关闭资源动作)。

  • “asdasd”.getBytes() 把字符串改成字符

  • InputStream.available()文件的大小字节

    • 对小文件可以使用
    • 对大文件最好不去使用
      在真正读数据的时候最好new一个1024的字节数组,循环读取文件

22-IO流(字节流-练习-复制MP3)

copy_01:建议的方法

copy_02:建议的方法

copy_03:不建议。 如果文件过大,要不断创建数组,很慢,如果文件过大,直接溢出。

copy_04:千万不要用,效率没有!读一个写一个很慢

package day21.cn.itcast.p7.io.bytestream.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyMp3Test {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {

        copy_4();

    }
//  千万不要用,效率没有!读一个写一个很慢
    public static void copy_4() throws IOException {
        FileInputStream fis = new FileInputStream("c:\\0.mp3");     
        FileOutputStream fos = new FileOutputStream("c:\\4.mp3");


        int ch = 0;

        while((ch =fis.read())!=-1){
            fos.write(ch);
        }

        fos.close();
        fis.close();
    }

    //不建议。 如果文件过大,要不断创建数组,很慢,如果文件过大,直接溢出
    public static void copy_3() throws IOException {
        FileInputStream fis = new FileInputStream("c:\\0.mp3");     
        FileOutputStream fos = new FileOutputStream("c:\\3.mp3");

        byte[] buf = new byte[fis.available()];
        fis.read(buf);
        fos.write(buf);
        fos.close();
        fis.close();
    }

    public static void copy_2() throws IOException {

        FileInputStream fis = new FileInputStream("c:\\0.mp3"); 
        BufferedInputStream bufis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream("c:\\2.mp3");
        BufferedOutputStream bufos = new BufferedOutputStream(fos);



        int ch = 0;

        while((ch=bufis.read())!=-1){
            bufos.write(ch);
        }

        bufos.close();
        bufis.close();
    }

    public static void copy_1() throws IOException {

        FileInputStream fis = new FileInputStream("c:\\0.mp3");     
        FileOutputStream fos = new FileOutputStream("c:\\1.mp3");

        byte[] buf = new byte[1024];

        int len = 0;

        while((len=fis.read(buf))!=-1){
            fos.write(buf,0,len);
        }

        fos.close();
        fis.close();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值