文件IO知识点续集

文件是存储在硬盘上的

操作系统把硬盘上的内容抽象成文件,供程序来使用

下面是read的使用方法

 

 往往读一个比较大的文件,需要循环读取

如何循环读取呢,我们看看代码

public static void main(String[] args) throws IOException {
        try(Reader reader = new FileReader("d:/test.txt")){
            while(true){
                char buf[] = new char[1024];
                int n = reader.read(buf);//把空数组填入内容
                if (n==-1){//如果读到的不是文件末尾,就会返回你读到多少个字符这样的个数
                    //读完了,读到文件末尾了
                    break;
                }
                for (int i = 0;i<n;i++){
                    System.out.print(buf[i]+" ");//打印出每个字符
                }
            }
        }
    }

 test是我放在D盘里的txt文件,里面的内容是"hello world"

运行结果如图

 这段代码的运行逻辑是在while里,创建一个数组,在数组中读入文件中的字符,尽可能填满,n是你读到多少个字符,然后判断n是否是-1,如果是-1说明已经读到文件末尾了,就可以跳出循环,如果n不等于-1,就打印字符

InputStream是字节流,用法和Reader非常相似

文本文件也可以使用字节流打开,只不过此时你读到的每个字节,就不是完整字符了

 

public class Demo7 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("d:/test.txt")){
            while (true){
                byte[]buf = new byte[1024];
                int n = inputStream.read(buf);
                if (n==-1){
                    break;
                }
                for (int i = 0;i<n;i++){
                    System.out.printf("%x ",buf[i]);//十六进制
                }
            }
        }
    }
}

运行结果如图

把文本的每个字节都读取出来,就能看到实际的中文是怎么编码的了 

Java虽然有char,更多的是使用String

此处,借助一些额外的工具类,就可以完成从字节/字符到字符串的转换

虽然也可以直接使用String 的构造方法完成char[]或者byte[]=>字符串的转换,但是这比较麻烦

===>麻烦

 我们可以这样做

public class Demo8 {
    public static void main(String[] args) throws IOException {
        try(InputStream inputStream = new FileInputStream("d:/test.txt")){
            Scanner scanner = new Scanner(inputStream);
            //此时就是从test.txt这个文件中读取数据
            String s = scanner.next();
            System.out.println(s);
        }
    }
}

运行结果如图

 以前学过的Scanner的操作,在这里完全试用

但是Scanner只是用来读文本文件的,不适合读取二进制文件

在标准库中,还提供了一些工具类,辅助更方便地读写二进制格式的文件

输出的使用方法和输入非常相似

write之前要打开文件,用完了也需要关闭文件

接下来我们看看代码

public class Demo9 {
    public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("d:/test.txt")){
            //write是可以直接写一个字符串,这个很方便
            writer.write("你好世界");
        }
    }
}

运行完以后文件内容变为

 我们发现之前的hellowould不见了

这是因为输出流对象(无论字节流还是字符流)会在打开文件之后,清空文件内容

我们也可以按照追加写方式打开,此时就不会清空内容了

public class Demo9 {
    public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("d:/test.txt",true)){
            //write是可以直接写一个字符串,这个很方便
            writer.write("你好世界");
        }
    }
}

我们在构造方法那里加上true

然后看看运行结果

 这样就不会清空之前的内容了

OutputStream使用方式完全一样.只不过write方法不能支持字符串参数,只能按照字节,或者字节数组来写入

读操作和写操作也能支持"随机访问",可以移动光标到指定位置,进行读写

接下来我们看一些实例

扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除文件

import java.io.File;
import java.util.Scanner;

public class Demo10 {
    private static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) {

        //先让用户输入一个目录,我们后续的查找都是根据这个目录进行的
        System.out.println("请输入要搜索的根目录");
        File rootPath = new File(scanner.next());
        //再让用户输入要搜索/要删除的关键词
        System.out.println("请输入要删除的关键词");
        String word = scanner.next();
        //判断一下当前目录是否有效
        if (!rootPath.isDirectory()){
            System.out.println("您此时输入的路径不是合法目录!");
            return;
        }
        //遍历目录,从根目录出发,根据深度优先(递归)的方式,进行遍历
        scanDir(rootPath,word);
    }
    public static void scanDir(File currentDir,String word){//currentDir是你当前根据哪一个目录进行扫描
        //先列出当前目录中都包含哪些内容
        File[] files = currentDir.listFiles();
        if (files == null||files.length ==0){
            //空的目录或者是非法的目录
            return;
        }
        //遍历列出的文件,分两个情况分别讨论
        for (File f:files){
            //加个日志,方便我们去看文件执行的过程
            System.out.println(f.getAbsolutePath());
            if (f.isFile()) {
                //如果当前文件是普通文件,看看文件名是否包含了Word,来决定是否要删除
                dealFile(f,word);
            }else{
                //如果当前文件是目录文件,就递归执行scanDir
                scanDir(f,word);
            }
        }
    }

    private static void dealFile(File f, String word) {
        //先判断当前文件名是否包含Word
        if (!f.getName().contains(word)){
            //此时这个文件不包含Word关键词,直接跳过
            return;
        }
        //包含Word就需要询问用户是否要删除该文件
        System.out.println("该文件是:"+f.getAbsolutePath()+",是否要确认删除?(Y/N)");
        String choice = scanner.next();
        if (choice.equals("Y")||choice.equals("y")){
            f.delete();
        }
        //如果是其他的值,都忽略
    }
}

运行测试结果如图

 这样就成功删除test文件了

这道题也是一道经典面试题,让你写一个代码递归遍历目录

下一题进行普通文件的复制,把一个文件给复制成另一个文件

如果要把文件A复制成文件B,只要打开A依次读出每个字节,再写入到文件B就行

import java.io.*;
import java.util.Scanner;

//完成文件复制
public class Demo11 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        //输入路径并且进行合法性判定
        System.out.println("请输入要复制的源文件路径:");
        String src = scanner.next();
        File srcFile = new File(src);
        if (!srcFile .isFile()){
            System.out.println("您输入的源文件路径非法");
            return;
        }
        System.out.println("请输入要复制到的目标路径:");
        String dest = scanner.next();
        File destFile = new File(dest);
        //不要求目标文件存在,但是得保证目标文件所在的目录是存在的
        //假设目标文件写作d:/tmp/cat2.jpg,就需要保证d:/tmp是存在的
        if (!destFile.getParentFile().isDirectory()){
            System.out.println("您输入的目标文件路径非法!");
            return;
        }
        //进行复制操作的过程,按照字节流打开
        try(InputStream inputStream = new FileInputStream(srcFile);
            OutputStream outputStream = new FileOutputStream(destFile)){
            while (true){
                byte[]buffer = new byte[1024];
                int n = inputStream.read(buffer);
                //System.out.println("n="+n);
                if (n==-1){
                    System.out.println("读取到eof,循环结束.");
                    break;
                }
                outputStream.write(buffer,0,n);
            }
        }
    }
}

运行结果如图

然后我们就能看见两个cat.jpg文件了

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值