day18-字符流

1. 字节流

1.1 字节缓冲流概述和构造方法【应用】

  • 字节缓冲流:

    • BufferedOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
    • BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
  • 构造方法

    • 字节缓冲输出流:BufferedOutputStream(OutputStream out)
    • 字节缓冲输入流:BufferedInputStream(InputStream in)

为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?

  • 子节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作

  • 演示代码

package com.day18;
/*
    字节缓冲流:
        BufferedOutputStream
        BufferedInputStream
     构造方法:
        字节缓冲输出流:BufferedOutputStream(OutputStream out)
        字节缓冲输入流:BufferedInputStream(InputStream in)
 */

import java.io.*;

public class BufferStreamDemo {
    public static void main(String[] args) throws IOException {
//        字节缓冲输出流:BufferedOutputStream(OutputStream out)
        FileOutputStream fos = new FileOutputStream("idea_test\\bos.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //合并
        BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("idea_test\\bos.txt"));
        //写数据
        bos1.write("hello\r\n".getBytes());
        bos1.write("world\r\n".getBytes());
        //释放资源
        bos1.close();
        bos.close();
//        字节缓冲输入流:BufferedInputStream(InputStream in)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("idea_test\\bos.txt"));

        //读数据
        //一次读一个字节数据
        int by;
        while ((by=bis.read())!=-1){
            System.out.print((char) by);
        }
        //一次读取一个字节数组数据
        byte[] bys = new byte[1024];
        //存储字节数组大小
        int len;
        while ((len = bis.read(bys)) != -1) {
            System.out.println(new String(bys, 0, len));
        }
        //释放资源
        bis.close();
    }
}

1.2 复制视频

  • 需求:把“E:\itcast\字节流复制图片.avi’复制到模块目录下的”字节流复制图片.vai"

  • 思路:

    • 根据数据源创建字节输入流对象
    • 根据目的地创建字节输出流对象
    • 读写数据,复制视频
    • 释放资源
  • 演示代码

package com.day18;

import java.io.*;

/*
需求:把“E:\\itcast\\字节流复制图片.avi'复制到模块目录下的”字节流复制图片.vai"

 思路:
   根据数据源创建字节输入流对象
   根据目的地创建字节输出流对象
   读写数据,复制视频
   释放资源

   四种方式实现复杂视频,并记录每种方式复杂视频的时间
        1:基本字节流一次读写一个字节  共耗时:220826毫秒
        2:基本字节流一次读写一个字节数组  333毫秒
        3:字节缓冲流一次读写一个字节  共耗时:833毫秒
        4:字节缓冲流一次读写一个字节数组  共耗时:65毫秒

 */
public class CopyAviDemo {
    public static void main(String[] args) throws IOException {
        //记录开始时间
        long startTime = System.currentTimeMillis();

        //复杂视频
        method1();
//        method2();
//        method3();
//        method4();

        //记录结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("共耗时:" + (endTime - startTime) + "毫秒");
    }

    //基本字节流一次读写一个字节  共耗时:220826毫秒
    private static void method1() throws IOException {
        //E:\\itcast\\字节流复制图片.avi
        //复制到模块目录下的”字节流复制图片.vai"
        FileInputStream fis = new FileInputStream("E:\\develop\\140_字节流复制视频.avi");
        FileOutputStream fos = new FileOutputStream("idea_test\\字节流复制图片.avi");

        int by;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }
        fos.close();
        fis.close();
    }

    //基本字节流一次读写一个字节数组  333毫秒
    private static void method2() throws IOException {
        //E:\\itcast\\字节流复制图片.avi
        //复制到模块目录下的”字节流复制图片.vai"
        FileInputStream fis = new FileInputStream("E:\\develop\\140_字节流复制视频.avi");
        FileOutputStream fos = new FileOutputStream("idea_test\\字节流复制图片.vai");

        byte[] bis = new byte[1024];
        int len;
        while ((len = fis.read(bis)) != -1) {
            fos.write(bis, 0, len);
        }

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

    //    字节缓冲流一次读写一个字节  共耗时:833毫秒
    private static void method3() throws IOException {
        //E:\\itcast\\字节流复制图片.avi
        //复制到模块目录下的”字节流复制图片.vai"
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\develop\\140_字节流复制视频.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("idea_test\\字节流复制图片.vai"));

        int by;
        while ((by = bis.read()) != -1) {
            bos.write(by);
        }
        bos.close();
        bis.close();
    }

    //字节缓冲流一次读写一个字节数组  共耗时:65毫秒
    private static void method4() throws IOException {
        //E:\\itcast\\字节流复制图片.avi
        //复制到模块目录下的”字节流复制图片.vai"
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\develop\\140_字节流复制视频.avi"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("idea_test\\字节流复制图片.vai"));

        byte[] bsy = new byte[1024];
        int len;
        while ((len = bis.read(bsy)) != -1) {
            bos.write(bsy, 0, len);
        }
        bos.close();
        bis.close();
    }
}

  • 基本字节流一次读写一个字节 共耗时:220826毫秒
  • 基本字节流一次读写一个字节数组 333毫秒
  • 字节缓冲流一次读写一个字节 共耗时:833毫秒
  • 字节缓冲流一次读写一个字节数组 共耗时:65毫秒

可以看出使用字节缓冲流每次读写一个字节数组是效率最高的

2. 字符流

为什么要出现字符流呢?

  • 一个汉字的存储
    • 如果是GBK编码,占用2个字节
    • 如果是UTF-8,占用3个字节
  • 由于字节流操作中文不是特别的方便,所以Java就提供字符流
    • 字符流=字节流+编码表

用字节流传输文本文件时,文本文件也会有编码,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢?

  • 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

2.1 编码表

基础知识:

  • 计算机中储存的信息都是用二进制数表示的;我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果
  • 按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制按照某种规则解析显示出来,称为解码。这里强调一下:按照A编码存储,必须按照A解析,这样才能显示正确的文本符合。否则就会导致乱码现象
  • 字符编码:就是一套自然语言的字符与二进制数之间的对应规则(A,65)

ASCII字符集

  • ASCII(American Standard Code for Information Interchange,美国信息交换标准代码):是基于拉丁字母的一个电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英语大小写字符、阿拉伯数字和西文符号)
  • 基本的ASCII字符集,使用7位表示一个字符,共128字符。ASCII的扩展字符集使用8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符的集合,包括各国文字、标点符号、图形符号、数字等

GBXXX字符集

  • GB2312:简体中文码表。一个小于127的字符的意义与原来相同,但是两个大于127的字符连在一起时,这样大约可以组合了包含7000多个简体汉字等。
  • GBK:最常用的中文码表。是在GB2312标准上的扩展规格,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
  • GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等

Unicode字符集

  • 为表示任意语言的任意而设计,业界的一种标准,也称为统一码、标准万国码。
  • UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码,互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。它使用一至四个字节为每个字符编码
    • 编码规则:
      • 128 US-ASCI字符,只需一个字节编码
      • 拉丁文等字符,需要二个字节编码,
      • 大部分常用字 (含中文) ,使用三个字节编码
      • 其他极少使用的Unicode辅助字符,使用四字节编码
  • 采用何种规则编码,就要采用对应规则解码,否则就会出现乱码

2.2 字符串中的编码解码问题

编码:

  • byte[] getBytes();使用平台的默认字符集将该String编码为一系列,将结果存储到新的字节数组中
  • byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中

解码:

  • String(byte[] bytes);通过使用平台的默认字符解码指定的字节数组来构造新的String

  • String(byte[] bytes,String charsetName):通过指定的字符解码指定的字节数组来构造新的String

  • 演示代码

package com.day18;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class StringDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s="中国";
        byte[] bys = s.getBytes();//[-28, -72, -83, -27, -101, -67]
        byte[] bytes = s.getBytes("UTF-8");//[-28, -72, -83, -27, -101, -67]
        byte[] gbks = s.getBytes("GBK");//[-42, -48, -71, -6]
        byte[] gb2312s = s.getBytes("GB2312");//[-42, -48, -71, -6]
        System.out.println(Arrays.toString(gb2312s));
        //平台默认的解码
        String s3 = new String(bys);//中国
        //错误的解码
        String s1 = new String(bys,"GBK");//涓浗
        //正确的解码
        String s2 = new String(bys, "UTF-8");//中国
        System.out.println(s3);
    }
}

采用何种规则编码,就要采用对应规则解码,否则就会出现乱码

2.3 字符流中的编码解码问题

字符流抽象基类

  • Reader:字符输入流的抽象类
  • Writer:字符输出流的抽象类

字符流中和编码解码问题相关的两个类

  • InputStreamReader

  • OutputStreamWriter

  • 演示代码

package com.day18;

import java.io.*;

public class ConversionStreamDemo {
    public static void main(String[] args) throws IOException {
//        OutputStreamWriter​(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
//        OutputStreamWriter​(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。
//        FileOutputStream fos = new FileOutputStream("idea_test\\osw.txt");
//        OutputStreamWriter osw =new OutputStreamWriter(fos);
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"));
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"), "UTF-8");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"),"GBK");
        osw.write("中国");
        osw.close();
//        InputStreamReader​(InputStream in) 创建一个使用默认字符集的InputStreamReader。
//        InputStreamReader​(InputStream in, String charsetName) 创建一个使用命名字符集的InputStreamReader。
//        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"));
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"),"GBK");
        //一次读取一个字符数据
        int ch;
        while ((ch=isr.read())!=-1){
            System.out.print((char) ch);
        }
        //一次读取一个字符数组
        char[] car= new char[1024];
        int len;
        while ((len=isr.read(car))!=-1){
            System.out.println(new String(car,0,len));
        }
        isr.close();
    }
}

采用何种规则编码,就要采用对应规则解码,否则就会出现乱码

  • InputStreamReader
    • 构造方法
    • InputStreamReader​(InputStream in) 创建一个使用默认字符集的InputStreamReader。
    • InputStreamReader​(InputStream in, String charsetName) 创建一个使用命名字符集的InputStreamReader。
  • OutputStreamWriter
    • 构造方法
    • OutputStreamWriter​(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
    • OutputStreamWriter​(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。

2.4 字符流写数据的5种方法

方法名说明
void write(int c)写一个字符
void write(char[] cbuf)写入一个字符数组
void write(char[] cbuf,int off,int len)写入字符数组的一部分
void write(String str)写一个字符串
void write(String str,int off,int len)写入一个字符串的一部分
  • 演示代码
package com.day18;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class OutputStreamWriterDemo {
    public static void main(String[] args) throws IOException {

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\osw.txt"));
        //写一个字符
        osw.write(97);
        osw.flush();
        osw.write(98);
        osw.flush();
        osw.write(99);
        //结果:abc

        //void write(char[] cbuf):写入一个字符数组
        char[] chs = {'a', 'b', 'c', 'd', 'e'};
        osw.write(chs);
        //结果:abcde

        //void write(char[] cbuf, int off,int len):x写入字符数组的一部分
        char[] chs1 = {'a', 'b', 'c', 'd', 'e'};
        osw.write(chs1, 0, 3);
        //结果:abc

        //void write(String str);写一个字符串
        osw.write("abcse");
        //结果:abcse

        //void write(String str,int off,int len);写一个字符串的一部分
        osw.write("abcde", 2, 2);
        //结果:cd

        //释放资源
        osw.close();
        
        //java.io.IOException: Stream closed
//        osw.write(100);
    }
}

补充

方法名说明
flush()刷新流,还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据

2.5 字符流读数据的2种方式

方法名说明
int read()一次读一个字符数据
int read(char[] cbuf)一次读一个字符数组数据
  • 实例代码
package com.day18;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\osw.txt"));
        //int read();一次读一个字符数据
        int ch;
        while ((ch = isr.read()) != -1) {
            System.out.println((char) ch);
        }
        //int read(char[] cbuf);一次读一个字符数组数据
        char[] chs=new char[1024];
        int len;
        while ((len=isr.read(chs))!=-1){
            System.out.print(new String(chs,0,len));
        }
        isr.close();
    }
}

2.6复制Java文件

需求:把模块目录下的“ConversionStreamDemo.java" 复制模块目录下”Copr.java"

思路:

  • 根据数据源创建字节输入流对象

  • 根据目的地创建字符输出流对象

  • 读写数据,复制文件

  • 释放资源

  • 演示代码

package com.day18;

import java.io.*;

public class CopyJavaDemo01 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符输入对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\ConversionStreamDemo.java"));
        //根据目的地创建字符输出对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\Copy.java"));
//        读写数据

        //一次读写一个字符数据
        int ch;
        while ((ch = isr.read()) != -1) {
            osw.write(ch);
        }
        //一次读写一个数组数据
        char[] car = new char[1024];
        int lne;
        while ((lne = isr.read(car)) != -1) {
            osw.write(car, 0, lne);
        }
        //释放资源
        osw.close();
        isr.close();
    }
}

2.7复制Java文件改造版

需求:把模块目录下的“ConversionStreamDemo.java" 复制模块目录下”Copr.java"
分析:

  • 转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化书写,转换流提供了对应的子类
  • FileReader:用于读取字符文件的便捷类
    • FileReader(String fileName)
  • FileWriter:用于写入字符文件的便捷类
    • FileWriter(String fileName)
  • 数据源和目的地的分析
    • 数据源:idea_test\ConversionStreamDemo.java—读数据—Reader—InputStreamReader–FileReader
    • 目的地:idea_test\Copy.java----写数据–Writer—OutputStreamWriter—FileWriter
      在需要使用编码转换的时候,还是需要使用转换类,即InputStreamReader\OutputStreamWriter

思路:

  • 根据数据源创建字节输入流对象

  • 根据目的地创建字符输出流对象

  • 读写数据,复制文件

  • 释放资源

  • 演示代码

package com.day18;

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

public class CopyJavaDemo02 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符输入流对象
        FileReader fr = new FileReader("idea_test\\ConversionStreamDemo.java");
        //根据目的地创建字符输出对象
        FileWriter fw = new FileWriter("idea_test\\Copy.java");
        //读写数据,复制文件
        //每次读取一个字符
        int ch;
        while ((ch = fr.read()) != -1) {
            fw.write(ch);
        }
        //每次读取一个字符数组
        char[] car = new char[1024];
        int lne;
        while ((lne = fr.read(car)) != -1) {
            fw.write(car, 0, lne);
        }
        //释放资源
        fw.close();
        fr.close();
    }
}

2.8字符缓冲流

字符缓冲流:

  • BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。 默认值足够大,可用于大多数用途。
  • BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。

构造方法

  • BufferedWriter(Writer out)
  • BufferedReader(Reader in)

-演示代码

package com.day18;

import java.io.*;

public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
//        FileWriter fw = new FileWriter("idea_test\\bw.txt");
//        BufferedWriter bufferedWriter = new BufferedWriter(fw);
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));
        //写入数据
        bw.write("hello\r\n");
        bw.write("world\r\n");
        bw.close();

        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //一次读取一个字符数据
        int ch;
        while ((ch = br.read()) != -1) {
            System.out.print((char) ch);
        }
        //一次读取一个字符数组数据
        char[] car = new char[1024];
        int len;
        while ((len = br.read(car)) != -1) {
            System.out.print(new String(car, 0, len));
        }
        br.close();
    }
}

2.9 案例:复制Java文件(字符缓冲流改进版)

需求:把模块目录下的“ConversionStreamDemo.java" 复制的模块目录下的"Copy.java"
思路:

  • 根据数据源创建字符缓冲输入流对象

  • 根据目的地创建字符缓冲输出流对象

  • 读写数据,复制文件

  • 释放资源

  • 代码演示

package com.day18;

import java.io.*;

public class CopyJavaDemo03 {
    public static void main(String[] args) throws IOException {
        //创建缓冲输入流
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\ConversionStreamDemo.java"));
        //创建缓冲输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\Copy.java"));
        //读写数据复制文件
        //一次读写一个字符数据
        int ch;
        while ((ch = br.read()) != -1) {
            bw.write(ch);
        }
        //一次读写一个字符数组数据
        char[] car = new char[1024];
        int len;
        while ((len = br.read(car)) != -1) {
            bw.write(car, 0, len);
        }
        //释放资源
        bw.close();
        br.close();
    }
}

2.10 字符缓冲流特有功能

  • BufferedWriter:

    • void newLine();写一行行分隔符字符串由系统属性定义
  • BufferedReader:

    • String readLine():读一行文字。结果包含行的内容的字符串,不包括任何终止字符,如果流的结尾到达,则为null
  • 演示代码

package com.day18;

import java.io.*;

public class BufferedStreamDemo02 {
    public static void main(String[] args) throws IOException {
       /* //创建字符缓冲流
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));

        //写数据
        for (int i = 0; i < 10; i++) {
            bw.write("hello" + i);
//            bw.write("\r\n");
            bw.newLine();
            bw.flush();
        }
        bw.close();*/
        //创建字符缓冲输入流
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //hello0
        //第一次读取数据
        String line = br.readLine();
        System.out.println(line);
        //hello1
        //第二次读取数据
        line = br.readLine();
        System.out.println(line);
        //多读两行  null
        line = br.readLine();
        System.out.println(line);
        line = br.readLine();
        System.out.println(line);
        String lines;
        while ((lines = br.readLine()) != null) {
            //只读内容不读换行符等内容,需要手动换行
            System.out.println(lines);
        }
        br.close();
    }
}

注意字符缓冲流(BufferedReader)的readLine只读数据不读终止符(换行)

2.11 复制Java文件(字符缓冲流特有功能改进版)

  • 需求:把模块目录下的“ConversionStreamDemo.java" 复制的模块目录下的"Copy.java"

思路:

  • 根据数据源创建字符缓冲输入流对象

  • 根据目的地创建字符缓冲输出流对象

  • 读写数据,复制文件(使用字符缓冲流特有功能实现)

  • 释放资源

  • 演示代码

package com.day18;

import java.io.*;

public class CopyJavaDemo04 {
    public static void main(String[] args) throws IOException {
        //根据数据源创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\ConversionStreamDemo.java"));
        //根据目的地创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\Copy.java"));
        //读写数据,复制文件
        //使用字节缓冲流特有功能实现
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //释放资源
        bw.close();
        br.close();
    }
}

注意使用readLine读数据,需要使用BufferedWiter.newLine()换行处理
然后进行BufferedWiter.flush()刷空缓冲流

2.12 IO小节

  • 字节流抽象类
    字节流
  • 字节流实现类
    实现类
  • 字符流抽象类
    字符流
  • 字符流实现类
    字符流实现类涉及编码问题要使用InputStreamReader等

2.13 案例:集合到文件

  • 需求:把ArrayList集合中的字符串数据写入到文本文件。要求:每个字符串元素作为文件中的一行数据
  • 思路
    • 创建ArrayList集合
    • 往集合中存储字符串元素
    • 创建字符缓冲输出流对象
    • 遍历集合,得到每一个字符串数据
    • 调用字符缓冲输出流对象的方法写数据
    • 释放资源
  • 演示代码
package com.day18;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ArrayListToTxtDemo {
    public static void main(String[] args) throws IOException {
        //创建ArrayList集合
        ArrayList<String> arrayList = new ArrayList<>();

        //往集合中存储字符串元素
        arrayList.add("hello");
        arrayList.add("world");
        arrayList.add("java");
        //创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\bw.txt"));
        //遍历集合,得到每一个字符串数据
        for (String s : arrayList) {
            //调用字符缓冲输出流对象的方法写数据
            bw.write(s);
            bw.newLine();
            bw.flush();
        }
        //释放资源
        bw.close();

    }
}

2.13 案例:文件到集合

  • 需求:把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个集合元素
  • 思路
    • 创建字符缓冲输入流对象
    • 创建ArrayList集合对象
    • 调用字符缓冲流输入流对象的方法读数据
    • 把读取到字符串数据储存到集合中
    • 释放资源
    • 遍历集合
  • 演示代码
package com.day18;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class TxtToArrayListDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //创建ArrayList集合对象
        ArrayList<String> arrayList = new ArrayList<>();
        //调用字符缓冲输入流对象的方法读数据
        String line;
        while ((line = br.readLine()) != null) {
            //把读取到的字符串储存到集合中
            arrayList.add(line);
        }
        //释放资源
        br.close();
        //遍历集合
        for (String s : arrayList) {
            System.out.println(s);
        }
    }
}

2.14案例:点名器

  • 需求:我有一个文件储存了班级同学的姓名,每一个名字占一行,要求通过程序实现随机点名器

  • 思路

    • 创建字节缓冲输入流对象
    • 创建ArrayList集合对象
    • 调用字符缓冲输入流对象的方法读数据
    • 把读取到的字符串储存到集合中
    • 释放资源
    • 使用Random生产一个随机数,随机数的范围在:[0,集合的长度)
    • 把第6步产生的随机数作为索引到ArrayList集合中获取值
    • 把第7步得到的数据输出到控制台
  • 演示代码

package com.day18;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

/**
 * @author 61443
 */
public class CallNameDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt"));
        //创建ArrayList集合对象
        ArrayList<String> arrayList = new ArrayList<>();
        //调用字符缓冲输入流对象的方法读数据
        String line;
        while ((line = br.readLine()) != null) {
            //把读取到字符串数据存储到集合中
            arrayList.add(line);
        }
        //释放资源
        br.close();
        //使用Random产生一个随机数,随机数的范围:[0,集合的长度)
        Random random = new Random();
        int anInt = random.nextInt(arrayList.size());
        //把产生的随机数作为索引到ArrayList集合中获取值
        String s = arrayList.get(anInt);
        //把得到的随机输出在控制台
        System.out.println(s);
    }
}

2.15案例:集合到文件(改进版)

需求:把ArrayList集合中的学生数据到文本文件。要求:每一个学生对象的数据作为文件中的一行数据个格式:学号,姓名,年龄,居住地
举例:itheima001,林青霞,30,西安

  • 思路:
    • 定义学生类
    • 创建ArrayList集合
    • 创建学生对象
    • 把学生对象添加到集合中
    • 创建字符缓冲输出流对象
    • 遍历集合,得到每个学生对象
    • 把学生对象的数据拼接成指定格式的字符串
    • 调用字符缓冲输出流对象的方法写数据
    • 释放资源
  • 演示代码

学生类

package com.day18;

/**
 * @author 61443
 */
public class Student {

    private String sid;

    private String name;

    private int age;

    private String address;

    public Student(String sid, String name, int age, String address) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public Student() {

    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        if (sid != null ? !sid.equals(student.sid) : student.sid != null) return false;
        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return address != null ? address.equals(student.address) : student.address == null;
    }

    @Override
    public int hashCode() {
        int result = sid != null ? sid.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + age;
        result = 31 * result + (address != null ? address.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Student{");
        sb.append("sid='").append(sid).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", address='").append(address).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

测试类

package com.day18;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ArrayListToFileDemo {
    public static void main(String[] args) throws IOException {
//        创建ArrayList集合
        ArrayList<Student> arrayList = new ArrayList<>();
        //        创建学生对象
        Student s1 = new Student("itheima011", "林青霞", 30, "西安");
        Student s2 = new Student("itheima012", "林青霞", 30, "西安");
        Student s3 = new Student("itheima013", "林青霞", 30, "西安");
//        把学生对象添加到集合中
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
//        创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\osw.txt"));
//        遍历集合,得到每个学生对象
        for (Student student : arrayList) {
//            把学生对象的数据拼接成指定格式的字符串
            StringBuilder builder = new StringBuilder();
            builder.append(student.getSid()).append(",").append(student.getName()).append(",").append(student.getAge()).append(",").append(student.getAddress());
//            调用字符缓冲输出流对象的方法写数据
            bw.write(builder.toString());
            bw.newLine();
            bw.flush();
        }
//        释放资源
        bw.close();
    }
}

2.15案例:集合到文件(改进版)

  • 需求:把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个学生对象的成员变量值 举例:itheima001,林青霞,30.西安

  • 思路:

    • 定义学生类
    • 创建字符缓冲输入流对象
    • 创建ArrayList集合对象
    • 调用字符缓冲输入流对象的方法读数据
    • 把读取到字符串数据用split() 进行分割,得到一个字符串数组
    • 创建学生对象
    • 把字符串数组中的每一个元素取出来对应的赋值给学生对象的成员变量值
    • 把学生对象添加到集合
    • 遍历集合
  • 演示代码

学生类

package com.day18;

/**
 * @author 61443
 */
public class Student {

    private String sid;

    private String name;

    private int age;

    private String address;

    public Student(String sid, String name, int age, String address) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public Student() {

    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        if (sid != null ? !sid.equals(student.sid) : student.sid != null) return false;
        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return address != null ? address.equals(student.address) : student.address == null;
    }

    @Override
    public int hashCode() {
        int result = sid != null ? sid.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + age;
        result = 31 * result + (address != null ? address.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Student{");
        sb.append("sid='").append(sid).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", address='").append(address).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

测试类

package com.day18;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class FileToArrayListDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("idea_test\\osw.txt"));
//        创建ArrayList集合对象
        ArrayList<Student> list = new ArrayList<>();
        //调用字符缓冲输入流对象的方法读数据
        String line;
        while ((line = br.readLine()) != null) {
            //把读取到字符串数据用split() 进行分割,得到一个字符串数组
            String[] split = line.split(",");
            //创建学生对象
            Student student = new Student();
//            把字符串数组中的每一个元素取出来对应的赋值给学生对象的成员变量值
            student.setSid(split[0]);
            student.setName(split[1]);
            student.setAge(Integer.valueOf(split[2]));
            student.setAddress(split[3]);
            //把学生对象添加到集合
            list.add(student);
        }
        //释放资源
        br.close();
        //遍历集合
        for (Student s : list) {
            System.out.println(s.getSid() + "," + s.getName() + "," + s.getAge() + "," + s.getAddress());
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘿嘿嘿1212

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值