zoukankan      html  css  js  c++  java
  • Java I/O流 03

    I/O流·字符流

    字符流FileReader

    * A:字符流是什么
      * 字符流是可以直接读写字符的 IO流
      * 字符流读取字符,就要先读取到字节数据,然后转换为字符;如果要写出字符,需要把字符转换为字节再写出

    * B:FileReader
      * FileReader类的read() 方法可以按照字符大小读取

    package com.heima.chario;
    
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Demo1_FileReader {
    
        public static void main(String[] args) throws IOException {
            // demo1();
            // demo2();
        }
    
        public static void demo2() throws FileNotFoundException, IOException {
            FileReader fr = new FileReader("xxx.txt");
            int c; // 默认返回的是int类型
            
            while ((c = fr.read()) != -1) {    // 通过项目默认的码表,一次读取一个字符
                System.out.println((char) c); // 强转为char类型
            }
            fr.close();
        }
    
        public static void demo1() throws FileNotFoundException, IOException {
            FileReader fr = new FileReader("xxx.txt"); // 创建字符输入流
            char c = (char) fr.read(); // 读取一个字符并强转为char类型
            
            System.out.println(c);
            fr.close(); // 关流
        }
    }
    FileReader

    字符流FileWriter

    * A:FileWriter类的 write()方法可以自动把字符转为字节写出

    package com.heima.chario;
    
    import java.io.FileWriter;
    
    public class Demo2_FileWriter {
    
        public static void main(String[] args) throws Exception {
            FileWriter fw = new FileWriter("yyy.txt"); // 创建字符输出流
            fw.write("大家好,基础班快接近尾声了,大家要努力啊!!"); // 写入字符串,底层通过编码表翻译后用字节写入
            fw.write(97);
            fw.close(); // 关流
        }
    }
    FileWriter

    什么情况下使用字符流

    * 字符流也可以拷贝文本文件,但不推荐是同,因为读取时会把字节转为字符,写入时会把字符转为字节
    * 程序如果只需要读取一段文本或者只需要写出一段文本的时候,可以使用字符流
      * 因为读取的时候是按照字符的大小读取的,不会出现半个中文的情况
      * 写入的是红可以直接将字符串写出,不用转换为字节

    * 字符流不可以拷贝非纯文本文件
      * 因为再读的时候会将字节转换为字符,在转换的过程中可能找不到对应的字符,就会用?代替
      * 如果读取为?,写出时也是?的字节,这样文件的乱码了

    用字符流拷贝文件

     * A:普通字符流拷贝

    * B:带缓冲的字符流
      * BufferedReader的 read()方法读取字符时会一次读取若干个字符到缓冲区,然后逐个返回给程序,降低读取文件的次数,提高效率
      * BufferedWriter的 write()方法写出字符时会先写到缓冲区,缓冲区写满后才会写到文件,降低写文件的次数,提高效率

    package com.heima.chario;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Demo3_Copy {
    
        public static void main(String[] args) throws IOException {
            // demo1();
            // demo2();
            // demo3();
            // demo4();
        }
    
        public static void demo4() throws FileNotFoundException, IOException {
            BufferedReader br = new BufferedReader(new FileReader("xxx.txt")); // 创建带缓冲的字符输入流,关联普通字符输入流
            BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
            
            int c;
            while ((c = br.read())!= -1) {
                bw.write(c);
            }
            
            br.close();
            bw.close();
        }
    
        public static void demo3() throws FileNotFoundException, IOException {
            FileReader fr = new FileReader("xxx.txt"); // 创建字符输入流
            FileWriter fw = new FileWriter("yyy.txt"); // 创建字符输出流
    
            char[] arr = new char[1024 * 8]; // 创建字符数组接收数据
            int len;
            while ((len = fr.read(arr)) != -1) { // 将文件上的数据读取到字符数组中
                fw.write(arr, 0, len);    // 将字符数组中的数据写到文件上
            }
            fr.close();
            fw.close();
        }
    
        public static void demo2() throws FileNotFoundException, IOException {
            // 字符流不能拷贝非纯文本文件
            FileReader fr = new FileReader("亲爱的小孩.mp3");
            FileWriter fw = new FileWriter("copy1.mp3");
            
            int c;
            while ((c = fr.read()) != -1) {
                fw.write(c);
            }
            fr.close();
            fw.close();
        }
    
        public static void demo1() throws FileNotFoundException, IOException {
            FileReader fr = new FileReader("xxx.txt"); // 创建字符输入流
            FileWriter fw = new FileWriter("zzz.txt"); // 创建字符输出流
    
            int c; // 接收每一个字符
            while ((c = fr.read()) != -1) {
                fw.write(c); // 将读取到的内容写入文件
            }
            
            fr.close(); // 关流
            fw.close(); // Writer类中有一个2k的小缓冲区,程序会将内容写到缓冲区内,关流会将缓冲区内的内容刷新到硬盘上
        }
    }
    Copy

    readLine() 和 newLine() 方法

    * BufferedReader的 readLine()方法可以读取一行字符(不包含换行符)

    * BufferedWriter的 newLine()方法可以输出一个跨平台的换行符

    package com.heima.chario;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Demo4_Buffered {
        /*
         * 带缓冲区的流中的特殊方法:
         * readLine():逐行读取
         * newLine():写出回车换行符
         */
        public static void main(String[] args) throws IOException {
            // demo1();
            // demo2();
        }
    
        public static void demo2() throws FileNotFoundException, IOException {
            BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); // 创建带缓冲的字符流
            BufferedWriter bw = new BufferedWriter(new FileWriter("aaa.txt"));
    
            String lineString;
            while ((lineString = br.readLine()) != null) {
                bw.write(lineString);
                //bw.write("
    ");
                bw.newLine();    // newLine 和 
     的区别是:前者是跨平台的,而后者仅在windows代表换行
            }
            
            br.close(); // 关流
            bw.close();
        }
    
        public static void demo1() throws FileNotFoundException, IOException {
            BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); // 创建带缓冲的字符流
            String lineString;
    
            while ((lineString = br.readLine()) != null) { // 逐行读取
                System.out.println(lineString);
            }
            br.close(); // 关流
        }
    }
    ReadLine

    将文本反转

    * 将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换

    package com.heima.test;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.ArrayList;
    
    public class Test1 {
        /*
         * 分析: 
         * 1、创建输入输出流对象 
         * 2、创建集合对象,把数据进行临时存储 
         * 3、将读到的数据存储在集合中
         * 4、倒着遍历集合,将数据写到文件上 
         * 5、关流
         * 
         * 注意事项:流对象尽量晚开早关
         */
        public static void main(String[] args) throws IOException {
            ArrayList<String> list = new ArrayList<String>(); // 创建空列表
            String lineString;
            BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); // 创建带缓冲的字符流
            
            while ((lineString = br.readLine()) != null) { // 从文件中逐行读取
                list.add(lineString); // 逐行存入列表中
            }
            br.close();    // 关流1
            
            //Collections.reverse(list); // 也可以调用集合工具类先反转,再正着遍历
            BufferedWriter bw = new BufferedWriter(new FileWriter("revzzz.txt"));
            for (int i = list.size() - 1; i >= 0; i--) { // 倒着遍历列表
                bw.write(list.get(i)); // 通过索引获取列表元素并写入文件中
                bw.newLine(); // 换行
            }
            bw.close(); // 关流2
        }
    }
    Test1

    LineNumberReader

    * LineNumberReader是BufferedReader的子类,具有相同的功能,并且可以统计行号
      * 调用 getLineNumber()方法可以获取当前行号
      * 调用 setLineNumber()方法可以设置当前行号

    package com.heima.chario;
    
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.LineNumberReader;
    
    public class Demo5_LineNumberReader {
    
        public static void main(String[] args) throws IOException {
            LineNumberReader lnr = new LineNumberReader(new FileReader("zzz.txt"));
            
            String lineString;
            lnr.setLineNumber(100);    // 设置初始的行号,默认为0,每readLine一次,行号就加一
            while ((lineString = lnr.readLine())!=null) {
                System.out.println(lnr.getLineNumber() + ":" + lineString);
            }
            lnr.close();
        }
    }
    LineNumberReader

    装饰设计模式

    package com.heima.chario;
    
    public class Demo6_Wrap {
        /*
         * 装饰设计模式的好处是:
         * 耦合性低,被装饰类的变化与装饰类的变化无关
         */
        public static void main(String[] args) {
            HeiMaStudent hms = new HeiMaStudent(new Student());
            hms.code();
        }
    }
    
    interface Coder {
        public void code(); // 定义抽象方法
    }
    
    class Student implements Coder {
    
        @Override
        public void code() {
            System.out.println("javase");
            System.out.println("javaweb");
        }
    
    }
    
    class HeiMaStudent implements Coder { // 目标是装饰Student类,对其进行强化
        // 获取被装饰类的引用
        private Student student; // 获取学生引用
        
        // 在构造方法中传入被装饰类的对象
        public HeiMaStudent(Student s) {
            this.student = s;
        }
    
        // 对原有的功能进行升级
        @Override
        public void code() {
            student.code();
            System.out.println("ssh");
            System.out.println("数据库");
            System.out.println("hadoop");
            System.out.println("...");
        }
    
    }
    Wrap

    使用指定的码表读写字符

    * FileReader是使用默认码表读取文件,如果需要使用指定码表读取,那么可以使用InputStreamReader(字节流,编码表)

    * FileWriter是使用默认码表写文件,如果需要使用指定码表写出,那么可以使用OutputStreamReader(字节流,编码表)

    package com.heima.chario;
    
    import java.io.*;
    
    
    public class Demo7_TransIO {
    
        public static void main(String[] args) throws IOException {
            // demo1();
            // demo2();
            // demo3();
        }
    
        public static void demo3() throws UnsupportedEncodingException, FileNotFoundException, IOException {
            // 采用带缓冲的字符流,进行更高效的读写,装饰设计模式的思想
            BufferedReader br = new BufferedReader
                    (new InputStreamReader(new FileInputStream("utf-8.txt"), "utf-8")); // 创建带缓冲的字符流,关联转换流
            BufferedWriter bw = new BufferedWriter
                    (new OutputStreamWriter(new FileOutputStream("gbk.txt"), "gbk"));
            
            int len;
            while ((len = br.read())!= -1) { // 使用内置的缓冲区读取数据
                bw.write(len);
            }
            
            br.close(); // 关流
            bw.close();
        }
    
        public static void demo2() throws UnsupportedEncodingException, FileNotFoundException, IOException {
            // 指定码表读和写字符
            InputStreamReader isr = new InputStreamReader(new FileInputStream("utf-8.txt"),"utf-8"); // 创建字符转换流,关联字节流
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk"); // 编码形式可以省略,省略默认为项目的编码表
            
            int c;
            while ((c = isr.read())!= -1) { // 逐个字符读取
                osw.write(c);
            }
            
            isr.close();
            osw.close();
        }
    
        public static void demo1() throws FileNotFoundException, IOException {
            // 用默认编码表读写,出现乱码
            FileReader fr = new FileReader("utf-8.txt"); // 内容由utf-8编码
            FileWriter fw = new FileWriter("gbk.txt"); // 内容由gbk编码
    
            int c;
            while ((c = fr.read()) != -1) {
                fw.write(c);
            }
    
            fr.close();
            fw.close();
        }
    }
    InputStreamReader

    获取文本上字符出现的次数

    * 获取文本上每个字符出现的次数,将结果写在 times.txt上

    package com.heima.test;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.TreeMap;
    
    public class Test2 {
        /*
         * 分析:
         * 1、创建带缓冲的输入流对象
         * 2、创建双列集合对象TreeMap
         * 3、将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储,如果包含这个键,就将键和值+1存储
         * 4、关闭输入流,创建输出流对象
         * 5、遍历集合,将集合的内容写到times.txt中
         * 6、关闭输出流
         */
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); //创建带缓冲的输入流对象
            TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>(); // 创建双列集合
            
            int c;
            while ((c = br.read())!= -1) { // 从文件中逐个读取字符
                char ch = (char)c;    // 向下强转
                /*if (!tm.containsKey(ch)) {
                    tm.put(ch, 1);
                }else {
                    tm.put(ch, tm.get(ch)+1);
                }*/
                tm.put(ch, !tm.containsKey(ch)? 1 : tm.get(ch)+1); // 将字符及其出现次数存储到双列集合中
            }
            br.close(); // 关闭输入流
            
            BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt")); // 创建输出流对象
            for (Character key : tm.keySet()) { // 遍历键的集合,获取每个键
                /*if (key == '
    ') {
                    bw.write("\r" + "=" + tm.get(key));
                    bw.newLine();
                } else if (key == '
    ') {
                    bw.write("\n" + "=" + tm.get(key));
                    bw.newLine();
                }else if (key == '	') {
                    bw.write("\t" + "=" + tm.get(key));
                    bw.newLine();
                }else {
                    bw.write(key + "=" + tm.get(key));
                    bw.newLine();                
                }*/
                
                switch (key) { // 将集合中的内容写到文件中
                case '	': {
                    bw.write("\t" + "=" + tm.get(key)); 
                    break;
                }
                case '
    ': {
                    bw.write("\r" + "=" + tm.get(key));
                    break;
                }
                case '
    ': {
                    bw.write("\n" + "=" + tm.get(key));
                    break;
                }
                
                default:
                    bw.write(key + "=" + tm.get(key));
                }
                bw.newLine(); // 输入换行
            }
            
            bw.close(); // 关闭输出流
        }
    }
    Test2

    试用版软件

    * 当我们下载一个试用版软件时,每执行一次就会提醒我们还有多少次使用的机会
    * 用IO知识,模拟试用版软件,试用10次,每执行一次, 提示一次还剩几次机会,如果次数到了,就提示:请购买正版

    package com.heima.test;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Test3 {
        /*
         * 分析:
         * 1、创建待缓冲的输入流对象,使用readLine()方法,保证数据的原样性
         * 2、将读到的字符串转换为int数
         * 3、对int数进行判断,如果大于0,就将其减一,并写回源文件;如果小于等于0,就提示"请购买正版软件"
         * 
         */
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader("config.txt"));
            String line = br.readLine(); // 整行读取
            int c = Integer.parseInt(line); // 将字符串型数字转换为int型数字
            br.close(); // 关闭输入流
    
            FileWriter fw = new FileWriter("config.txt"); // 会清空config.txt文件
            if (c > 0) {
                System.out.println("您还有 " + c-- + "次机会");
                fw.write(c + ""); // 打印字符串
            } else {
                System.out.println("试用次数以耗尽,请购买正版");
                fw.write(0 + ""); // 将0写回文件,否则config.txt就是空的了
            }
            
            fw.close(); // 关闭输出流,如果忘记关流,数据在缓冲区内不会被刷过去
            
        }
    }
    Test3

    递归

    * 递归的弊端:不能调用太多次,容易导致栈溢出
    * 递归的好处:不用知道循环次数

    * 练习:从键盘输入接收一个文件夹路径,打印出该文件夹下所有的 .java文件

    package com.heima.test;
    
    import java.io.File;
    import java.util.Scanner;
    
    public class Test4 {
        /*
         * 分析:
         * 1、从键盘接收一个文件夹路径
         *         如果录入的是不存在的,给提示
         *         如果录入的是文件路径,也给提示
         *         如果是文件夹路径,直接返回
         * 
         * 2、获取到该文件夹下的所有文件和文件夹,存储在一个file数组中
         * 
         * 3、遍历数组,对每一个文件或文件夹做判断,
         *         如果是文件,并且后缀是.java就打印;
         *         如果是文件夹,就递归调用
         *
         * 注意:构造方法不能递归调用
         */
        
        public static void main(String[] args) {
            File dir = getDir(); // 获取文件夹路径
            printJavaFile(dir); // 调用递归方法
            
        }
        
        /*
         * 获取键盘录入的文件夹路径
         * 1、返回值类型,File
         * 2、不需要参数
         */
        public static File getDir() {
            Scanner sc = new Scanner(System.in); // 创建键盘录入对象
            System.out.println("请输入一个文件夹路径"); // 提示输入
            while (true) { // 定义无限循环
                String liString = sc.nextLine(); // 将键盘录入的文件夹路径存储
                File dir = new File(liString); // 将录入的内容封装成File对象
                if (!dir.exists()) { // 对File对象进行一系列判断
                    System.out.println("您录入的文件夹路径不存在,请重新录入");
                } else if (dir.isFile()) {
                    System.out.println("您录入的是文件路径,请您录入文件夹路径");
                } else {
                    sc.close();
                    return dir; // 返回File对象
                }
            }
        }
        /*
         * 获取文件夹路径下的所有.java文件
         * 1、返回值为void
         * 2、参数列表为File dir
         */
        public static void printJavaFile(File dir) { // 传入文件夹路径
            File[] subFiles = dir.listFiles(); // 获取该路径下所有的文件和文件夹
            for (File subfile : subFiles) { // 遍历File数组
                if (subfile.isFile() && subfile.getName().endsWith(".java")) { // 判断是否符合条件
                    System.out.println(subfile.getName()); // 如果符合,就打印
                } else if (subfile.isDirectory()) { // 如果是文件夹
                    printJavaFile(subfile); // 递归调用
                }
            }
        }
    }
    Test4
  • 相关阅读:
    js 数组相减
    js 对象数组去重
    vue 首次不触发watch的解决方法
    "神药"推荐--紫花地丁
    openstack 平台添加 nvidia vGPU
    string易错点整理总结
    CentOS安装图形界面
    CentOs安装ssh和scp
    数组把0移到末尾
    Windows下Celery安装与下使用
  • 原文地址:https://www.cnblogs.com/zhaochuming/p/12712270.html
Copyright © 2011-2022 走看看