javaIO字符流&&浅尝文件递归

目录

字符流FileReader

FileWriter

字符流的拷贝

什么情况下使用字符流

字符流是否可以拷贝纯文本文件

自定义字符流数组

带缓冲的字符流

readLine()和newLine()

将文本反转

LineNumberReader

装饰设计模式

使用指定码表读写字符

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

试用版软件

 F递归

 File递归练习


 

字符流FileReader

字符流是什么?

        字符流是可以直接读写字符的IO流

字符流读取字符,就要先读取到字节数据,然后转为字符,如果要写出字符,需要把字符转为字节再写出

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

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

public class demo1 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("xxx.txt");
        int c ;
        while((c = fr.read())!=-1){      //通过项目默认的码表一次读取一个字符
            System.out.print((char)c);
        }
        fr.close();
    }
}

FileWriter

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

public class demo2 {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("yyy.txt");
        fw.write("大家好。");
        fw.close();
    }
}

字符流的拷贝

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

public class demo3 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("xxx.txt");
        FileWriter fw = new FileWriter("yyy.txt");

        int c;
        while((c=fr.read())!=-1) {
            fw.write(c);
        }
        fr.close();
        fw.close();       //writer类中有一个2k的小缓冲区,如果不关流就会将 
                              //内容写到缓冲区里
    }
}

什么情况下使用字符流

 

字符流也可以拷贝文本文件,但是不推荐使用,因为读取时会把字节转为字符,写出时还要把字符转回字节

程序需要读取一段文本,或者需要写出一段文本的时候可以使用字符流

        读取的时候是按照字符的大小读取的不会出现半个中文,写出的时候可以直接将字符串写出不用转换为字节数组

字符流是否可以拷贝纯文本文件

不可以拷贝纯文本文件

因为再读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字节,就会用?代替,写出的时候会将字符转换成字节写出去,如果是?,直接写出之后的文件就乱了看不了了

自定义字符流数组

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

public class demo4 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("xxx.txt");
        FileWriter fw = new FileWriter("yyy.txt");
        int len;
        char[] arr = new char[1024];
        while((len=fr.read(arr)) != -1){
            fw.write(arr,0,len);
 
        }
        fw.close();
        fr.close();
    }
}

带缓冲的字符流

import java.io.*;

public class demo5 {
    public static void main(String[] args) throws 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();
    }
}

readLine()和newLine()

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

BufferedWrite的newLine()方法可以输出一个跨平台的换行符号"\r\n"

import java.io.*;

public class demo6 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
        String line;
        while((line = br.readLine()) != null){
            bw.write(line);
            //bw.write("\r\n");  //只支持windows
            bw.newLine();   //跨平台
        }
        br.close();
        bw.close();
    }
}

将文本反转

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

import java.io.*;
import java.util.ArrayList;

public class test {
    public static void main(String[] args) throws IOException {
   
      
        //创建临时存储集合并将读到数据存储进去
        ArrayList<String> al = new ArrayList<>();
        String line;
        BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
        while((line = br.readLine())!=null){
            al.add(line);
        }
        br.close();
         BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
        //将存储在集合中的临时数据倒叙写到文件上
        for(int i = al.size()-1;i>=0;i--){
            bw.write(al.get(i));
            bw.newLine();
        }
        bw.close();
 
    }
}

 注意事项:流对象尽量晚开早关

LineNumberReader

LineNumberReader是BufferedReader的子类,具有相同的功能,并且可以统计行号

        调用getLineNumber()方法获取当前行号

        调用setLineNumber()方法设置当前行号

装饰设计模式

public class demo7{
    public static void main(String[] args) {
        ketang ket = new ketang(new Student());
        ket.code();
    }
}
interface Coder {
    public void code();
}
class Student implements Coder {

    @Override
    public void code() {
        System.out.println("java");
    }
}
class ketang implements Coder {
    //1.获取被装饰类的引用
    private Student s;   //获取学生引用
    //2.在构造方法中传入被装饰类的对象
    public ketang(Student s) {
        this.s = s;
    }
    //3.对原有的功能进行升级
    @Override
    public void code() {
        s.code();
        System.out.println("安卓");
        System.out.println("...");
    }
}

降低耦合性,被装饰的类的变化与装饰类的变化无关

使用指定码表读写字符

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

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

import java.io.*;


public class demo8 {
    public static void main(String[] args) throws 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 ch;
        while((ch = br.read()) != -1){
            bw.write(ch);
        }
        bw.close();
        br.close();
    }
}

图解:由于字符流相当于内置了一个编码表,因此这里用字节流

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

import java.io.*;
import java.util.TreeMap;

public class test3 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("xxx.txt"));
        TreeMap<Character,Integer> tm = new TreeMap<>();
        int ch;
        while((ch = br.read())!=-1){
            char c = (char)ch; //向下强转
//            if(!tm.containsKey(c)){
//                tm.put(c,1);
//            }else{
//                tm.put(c,tm.get(c)+1);
        //    }
            tm.put(c,!tm.containsKey(c) ? 1 : tm.get(c)+1);
        }
        br.close();
        BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt"));
        for(Character k : tm.keySet()){
            switch(k) {
                case'\t':
                    bw.write("\\t"+ "=" + tm.get(k));
                    break;
                case'\n':
                    bw.write("\\n"+ "=" + tm.get(k));
                    break;
                case'\r':
                    bw.write("\\r" + "=" + tm.get(k));
                    break;
                default:
                    bw.write(k + "=" + tm.get(k));
                    break;
            }
            bw.newLine();
        }
        bw.close();
    }
}

试用版软件

当我们下载一个试用软件,没有购买正版时,每执行一次就会提醒我们还有多少次试用机会,模拟试用软件,当试用次数用完之后提示购买正版

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

public class test4 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("www.txt"));
        String line = br.readLine();
        int times = Integer.parseInt(line);
        if(times>0){
            System.out.println("您还有"+times--+"次试用机会");
            FileWriter fw = new FileWriter("www.txt");
            fw.write(times + "");
            fw.close();
        }else{
            System.out.println("您试用次数已经完了,请购买正版");

        }
        br.close();
    }
}

 F递归

递归的弊端是不能调用次数过多,容易导致栈内存溢出

好处是不用知道循环次数,只要找到递归出口跟入口就好了

构造方法是否可以递归调用:不可以,没有递归出口,不断创建新对象,死循环了。

递归调用是否必须有返回值:不一定(可以有也可以没有)

典型递归问题:

5!=5*4*3*2*1

public static int fun(int num) {
        if(num == 1){

                return num;

        }else {

                return num *fun(num-1);

 

 File递归练习

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

import java.io.File;
import java.util.Scanner;
public class teste {
    public static void main(String[] args) {
        File f = getdir();
        digui(f);

    }
    public static File getdir() {
        Scanner sc = new Scanner(System.in);
        while (true) {
            String s = sc.nextLine();
            File f = new File(s);
            if (f.isFile()) {
                System.out.println("您输入的是文件,请重新输入");
            } else if (!f.exists()) {
                System.out.println("您输入的路径不存在,请重新输入");
            } else {
                return f;
            }
        }
    }
    public static void digui(File f) {
        File[] subFiles = f.listFiles();
        for(File s : subFiles) {
            if(s.isFile()&&s.toPath().endsWith(".java")){
                System.out.println(s);
            } else if(s.isDirectory()){
                digui(s);
            }
        }
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值