Java基础复习22

二十二、流

1.分类

  按操作数据单位不同分为:字节流(8bit)(处理图片视频),字符流(char 16bit)(处理.txt文件)
  按数据流的流向不同分为:输入流,输出流(输入输出是对于内存而言,我们站在内存的角度)
  按流的角色不同分为:节点流(操作文件),处理流(操作流)

2.流的体系结构

  抽象基类       节点流(或文件流)           缓冲流(处理流的一种)
  InputStream       FileInputStream (read(byte[] buffer))       BufferedInputStream (read(byte[] buffer))
  OutputStream         FileOutputStream (write(byte[] buffer,0,len)  BufferedOutputStream (write(byte[] buffer,0,len) / flush()
  Reader         FileReader (read(char[] cbuf))          BufferedReader (read(char[] cbuf) / readLine())
  Writer           FileWriter (write(char[] cbuf,0,len)       BufferedWriter (write(char[] cbuf,0,len) / flush()

3.读入.txt操作

  用字符流读入.txt的步骤
  1.实例化File类的对象,指明要操作的文件
    File file = new File("hello.txt");//相较于当前Module
  2.提供具体的流
    FileReader fr = new FileReader(file);
    要注意的是会报异常,我们要用try catch包起来,因为如果不包起来,用throws方法向上抛,在出现异常后导致下面的代码不被执行,流的close操作就不会被执行造成内存的浪费,所以要将close方法放在finally中
  3.数据的读入
    read():返回读入的一个字符。如果达到文件末尾,返回-1
    read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1
    该方法需要注意的是返回的是读的字符的个数,比如数组长度是5,读取的文件里是helloworld123,每次读取5个字符,第一次hello,第二次world,第三次123,但第三次cbuf数组中存储的是123ld
    while((data = fr.read()) != -1)
  4.流的关闭操作
    fr.close();
    为了避免上边第二步出现异常导致fr对象未被创建,导致这里出现空指针异常,我们使用if(fr != null){fr.close();}
  操作的抽象化:
  1.File类的实例化
  2.FileReader流的实例化
  3.读入的操作
  4.资源的关闭
  说明点:
  1.read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
  2.异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
  3.读入的文件一定要存在,否则就会报FileNotFoundException

4.写出.txt操作

  用字符流写出.txt的步骤
  1.提供File类的对象,指明写出到的文件
    File file = new File("hello1.txt");
  2.提供FileWriter的对象,用于数据的写出
    fw = new FileWriter(file,false);
  3.写出的操作
    fw.write("I have a dream!\n");
    fw.write("you need to have a dream!");
  4.流资源的关闭
    fw.close();
  不能使用字符流处理图片等字节数据

5.乱码

  UTF-8中abc123等都用1个字节存储,汉字如"你好世界"每个汉字用3个字节存储
  所以使用字节流处理文本文件碰到里边有中文可能会出现乱码

  结论:
    1.对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
    2.对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理  

6.处理流之一,缓冲流的使用

  通常开发中我们不常用节点流如:FileInputStream等等,因为它太慢了,我们在FileInputStream的基础上再嵌套一个流,这种流就叫做处理流,这种流里边有缓冲区,能大大提升流的传输速度

  1.缓冲流:
    BufferedInputStream
    BufferedOutputStream
    BufferedReader
    BufferedWriter
  2.作用:提升流的读取、写入的速度
  提高读写速度的原因:内部提供了一个缓冲区
  3. 处理流,就是“套接”在已有的流的基础上

7.缓冲流复制一个图片的过程

  1.造文件
    File srcFile = new File("爱情与友情.jpg");
    File destFile = new File("爱情与友情3.jpg");
  2.造流
    2.1 造节点流
      FileInputStream fis = new FileInputStream((srcFile));
      FileOutputStream fos = new FileOutputStream(destFile);
    2.2 造缓冲流
      bis = new BufferedInputStream(fis);
      bos = new BufferedOutputStream(fos);
  3.复制的细节:读取、写入
    byte[] buffer = new byte[10];
    int len;
    while((len = bis.read(buffer)) != -1){ //通过read方法将数据都放入了buffer[]中,可以提取来看
      bos.write(buffer,0,len);
      bos.flush(); //刷新缓冲区,write()方法中已经调了
  4.资源关闭
    要求:先关闭外层的流,再关闭内层的流
    说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略

8.处理流之二,转换流的使用

  1.转换流:属于字符流
    InputStreamReader:将一个字节的输入流转换为字符的输入流
    OutputStreamWriter:将一个字符的输出流转换为字节的输出流
  注意:用字节流读取文本文件,在内存中查看时会出现乱码的问题,我们可以在使用字节流的基础上对它进行转换,使用转换流把它转换为与文本文件对应的编码形式在内存层面查看;然后用字符流输出时,使用转换流再对字符流进行转换,转换为字节流,比如之前的文件用UTF-8存储,可以使用转换流转换成GBK的方式存储
  2.作用:提供字节流与字符流之间的转换
  3. 解码:字节、字节数组 --->字符数组、字符串
    编码:字符数组、字符串 ---> 字节、字节数组
  4.字符集
    ASCII:美国标准信息交换码
      用一个字节的7位可以表示
    ISO8859-1:拉丁码表。欧洲码表
      用一个字节的8位表示
    GB2312:中国的中文编码表。最多两个字节编码所有字符
    GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
    Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示
    UTF-8:变长的编码方式,可用1-4个字节来表示一个字符

9.标准输入输出流

  1.标准的输入、输出流
    System.in:标准的输入流,默认从键盘输入 //in是InputStream类型的,即输入型字节型
    System.out:标准的输出流,默认从控制台输出 //out是PrintStream类型的,即打印流
  2.System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流
    通过System方法的重新指定,可以改变in和out的输入输出位置,不再是默认的位置

  3练习:
    从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,直至当输入“e”或者“exit”时,退出程序。

  方法一:使用Scanner实现,调用next()返回一个字符串
  方法二:使用System.in实现。System.in ---> 转换流 ---> BufferedReader的readLine()

10.打印流:PrintStream 和PrintWriter

  提供了一系列重载的print() 和 println()
  PrintStream ps = null;
  try {
    FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
    // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
    ps = new PrintStream(fos, true);
    if (ps != null) {// 把标准输出流(控制台输出)改成文件
      System.setOut(ps);
    }

    for (int i = 0; i <= 255; i++) { // 输出ASCII字符
      System.out.print((char) i);
      if (i % 50 == 0) { // 每50个数据一行
        System.out.println(); // 换行
      }
    }

  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } finally {
    if (ps != null) {
      ps.close();
    }
  }
  上述代码通过System.setOut()方法把out重置成了ps,输出位置不是默认的控制台了而是对应的文件目录下

11.数据流

  数据流,也是一种处理流
    1.DataInputStream 和 DataOutputStream
    2.作用:用于读取或写出基本数据类型的变量或字符串
  把数据放入内存中不靠谱,就可以把数据通过这种流写到磁盘中
  //1.创建文件创建流
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
  //2.流的读写操作
    dos.writeUTF("刘建辰");
    dos.flush();//刷新操作,将内存中的数据写入文件
    dos.writeInt(23);
    dos.flush();
    dos.writeBoolean(true);
    dos.flush();
  //3.流的关闭
    dos.close();

posted @ 2021-03-30 17:02  天真爱吃肉  阅读(69)  评论(0)    收藏  举报