Java学习记录 Day17(IO流)

Day 17

2019年5月18日。
这是我学习Java的第十七天。
这一天,我学到了以下的知识。

IO流

IO流,用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,而Java用于操作流的对象都在IO包中

IO流按照数据流向,可分为:输入流(从硬盘读取数据到内存),输出流(从内存写入数据到硬盘)

IO流按照数据类型,可分为:

  • 字节流
    可以读写任何类型的文件,比如音频、视频、文本文件
    抽象基类如下:

    • InputStream
      常用具体子类:1.FileInputStream
      构造方法:FileInputStream(File file)通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定
      FileInputStream(String name)通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定

      常用的成员方法

      • 读取功能
        • int read(byte[] b)一次读取一个字节数组
          - 当该方法返回 -1 时,表明已经读完了数据。一般可用该值来判断数据是否已经遍历完成
      • 关闭功能
        • public void close() throws IOException关闭文件流,释放资源

      2.BufferedInputStream
      为了对应BufferedOutputStream,Java提供了BufferedInputStream
      构造方法:BufferedInputStream(InputStream in)创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用

    • OutputStream
      常用具体子类:1.FileOutputStream
      构造方法:FileOutputStream(File file)创建一个向指定 File 对象表示的文件中写入数据的文件输出流
      FileOutputStream(String name)创建一个向具有指定名称的文件中写入数据的输出文件流
      常用的成员方法

      • 写入功能
        • public void write(int b)写一个字节 超过一个字节 砍掉前面的字节
        • public void write(byte[] b)写一个字节数组
        • public void write(byte[] b,int off,int len)写一个字节数组的一部分
      • 关闭功能
        • public void close() throws IOException关闭文件流,释放资源
          面试题:为什么一定要close()?
          a: 通知系统释放关于管理a.txt文件的资源
          b: 让Io流对象变成垃圾,等待垃圾回收器对其回收

      2.BufferedOutputStream
      字节流一次读写一个数组的速度,明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流,即BufferedOutputStream
      构造方法:BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流

  • 字符流
    只能读写文本文件
    由于字节流操作中文不是特别方便,所以,java就提供了字符流
    介绍字符流之前,首先介绍编码和解码的概念:

    • 编码
      - 把一个字符串转换成一个字节数组
      - public byte[] getBytes()使用平台的默认字符集将此 String编码为 byte 序列,并将结果存储到一个新的 byte 数组中
      - public byte[] getBytes(String charsetName)使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中

    • 解码
      - 把字节数组转换成字符串
      - public String(byte[] bytes)通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String
      - public String(byte[] bytes, String charsetName)通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String

    抽象基类如下:

    • Writer
      常用具体子类:1.OutputStreamWriter——FileWriter(便携类)
      构造方法:OutputStreamWriter(OutputStream out)根据默认编码(GBK)把字节流的数据转换为字符流
      OutputStreamWriter(OutputStream out,String charsetName)根据指定编码把字节流数据转换为字符流
      常用的成员方法

      • 写入功能
        • public void write(int c)写一个字符
        • public void write(char[] cbuf)写一个字符数组
        • public void write(char[] cbuf,int off,int len)写一个字符数组的一部分
        • public void write(String str)写一个字符串
        • public void write(String str,int off,int len)写一个字符串的一部分

    2.BufferedWriter
    高效的字符输出流
    构造方法:public BufferedWriter(Writer w)创建一个使用默认大小输出缓冲区的缓冲字符输出流
    特殊方法:public void newLine()根据系统来决定换行符,具有系统兼容性的换行符l

    • Reader
      常用具体子类:1.InputStreamReader——FileReader(便携类)
      构造方法:InputStreamReader(InputStream is)用默认的编码(GBK)读取数据
      InputStreamReader(InputStream is,String charsetName)用指定的编码读取数据
      常用的成员方法

      • 读取功能
        • public int read()一次读取一个字符
        • public int read(char[] cbuf)一次读取一个字符数组,如果没有读到,则返回-1

    2.BufferedReader
    高效的字符输入流
    构造方法:public BufferedReader(Reader e)创建一个使用默认大小输入缓冲区的缓冲字符输入流
    特殊方法:public String readLine()一次读取一行数据 ,是以换行符为标记的,读到换行符就换行,没读到数据返回null

IO流的异常处理

IO流的异常处理,分为字节流和字符流

  • 字节流
    以FileOutputStream为例,代码如下
public class MyTest {
    public static void main(String[] args) {
        //流的异常处理
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("d.txt");
            out.write(100);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 字符流

以InPutStreamReader和OutputStreamWriter为例,代码如下

public class MyTest {
    public static void main(String[] args) {
        //处理流的异常
        //一次多写一些
        InputStreamReader in = null;
        OutputStreamWriter out = null;
        try {
            in = new InputStreamReader(new FileInputStream("MyTest.java"));
            out = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\MyTest.java"));
            //定义一个字符缓冲区
            char[] chars = new char[2000];
            int len = 0;//记录每次读取到的有效字符个数
            while ((len = in.read(chars)) != -1) {
                out.write(chars, 0, len);
                out.flush();
            }
        } catch (IOException e) {
            //处理逻辑,默认打印异常的详细堆栈信息
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

IO流的经典算法

  • ArrayList集合中的字符串数据存储到文本文件中,以及将文本文件中的数据反向读入到ArrayList集合中
    代码如下
//1.ArrayList集合中的字符串数组存储到文本文件
public class MyTest {
    public static void main(String[] args) throws IOException {
        //需求:把ArrayList集合中的字符串数据存储到文本文件
        ArrayList<String> list = new ArrayList<>();
        list.add("冯小刚");
        list.add("张艺谋");
        list.add("宁浩");
        list.add("徐峥");
        list.add("小四");
        //把集合中的数据保存到文件文件中
        //思路,遍历集合,取出数据写入文本文件
        BufferedWriter writer = new BufferedWriter(new FileWriter("username.txt"));
        for (String s : list) {
            writer.write(s);
            writer.newLine();
            writer.flush();
        }
        writer.close();
    }
}
//2.文本文件中的数据反向读入到ArrayList集合
public class MyTest2 {
    public static void main(String[] args) throws IOException {
        //需求是,把文本文件中的数据读取到集合中
        ArrayList<String> list = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new FileReader("username.txt"));
        while (true){
            String s = reader.readLine();
            if(s!=null){
                list.add(s);
            }else{
                break;
            }

        }

        System.out.println(list);
    }
}
  • 多级文件夹复制
    代码如下
public class HomeTest {
    public static void main(String[] args) throws IOException {
        //需求:复制多级文件夹
        //1.封装源文件夹
        File srcFolder = new File("C:\\test2");
        //2.封装目标文件夹
        File targetFolder = new File("D:\\test2");
        if (!targetFolder.exists()) {
            targetFolder.mkdirs();
        }
        //进行复制
        copyFolder(srcFolder, targetFolder);
        System.out.println("复制完成");

    }

    private static void copyFolder(File srcFolder, File targetFolder) throws IOException {
        //遍历源文件夹下,所有的文件,复制到目标文件夹下去
        File[] files = srcFolder.listFiles();
        for (File f : files) {
            if(f.isFile()){
                copyFiles(f, targetFolder);
            }else{
                //targetFolder = new File(targetFolder.getPath() + "\\" + f.getName());
                //递归
                File file = new File(targetFolder,f.getName());
                if (!file.exists()) {
                    file.mkdirs();
                }
                copyFolder(f, file);
            }
        }
    }


    //复制文件
    private static void copyFiles(File f, File targetFolder) throws IOException {
        //使用字节流来复制
        FileInputStream in = new FileInputStream(f);//封装源文件
        //封装目标文件
        //File file = new File(targetFolder, f.getName());
        //System.out.println(file);
        FileOutputStream out = new FileOutputStream(new File(targetFolder, f.getName()));
        int len = 0;
        byte[] bytes = new byte[1024 * 8];
        while ((len = in.read(bytes)) != -1) {
            out.write(bytes, 0, len);
            out.flush();
        }
        //是否资源
        in.close();
        out.close();
    }
}
  • 录入学生信息到文件中
    代码如下
//学生类
public class Student implements Comparable<Student>{
    private String name;
    private int score;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return score;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", grade=" + score +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return score == student.score &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, score);
    }

    @Override
    public int compareTo(Student o) {
        int num=this.score-o.score;
        int num2=num==0?this.name.compareTo(o.name):num;
        return num2;
    }
}
//测试类
public class HomeTest {
    public static void main(String[] args) throws IOException {
        //需求: 键盘录入学生信息按照总分排序并写入文本文件
        Scanner scanner = new Scanner(System.in);
        Student student;
        TreeSet<Student> treeSet = new TreeSet<>();
        BufferedWriter buf = new BufferedWriter(new FileWriter("Student.txt"));
        for (int i = 1; i < 4; i++) {
            scanner = new Scanner(System.in);
            student = new Student();
            System.out.println("请输入第" + i + "位学生的姓名");
            String name = scanner.nextLine();
            student.setName(name);
            System.out.println("请输入第" + i + "位学生的成绩");
            int score = scanner.nextInt();
            student.setAge(score);
            treeSet.add(student);
        }
        buf.write(treeSet.toString());
        buf.close();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41151659/article/details/90320168