【JavaEE】文件操作(IO)

目录

1.文件操作(IO)

1.1文件操作定义 

1.2绝对路径与相对路径

1.3文本文件与二进制文件 

2.Java中操作文件 

2.1File类

2.1.1构造方法 

2.1.2常用方法

3.文件内容的读写

2.1输入流概述

2.1.1FileInputStream概述

2.1.2 FileReader概述

2.3输出流概述

2.3.1FileOutputStream概述

2.3.2FileWriter概述

3.文件io小练习 


1.文件操作(IO)

1.1文件操作定义 

IO是input和output的缩写,翻译为中文就是输入流、输出流。

IO操作就是将数据写入内存或从内存输出的过程,也指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接 。

在输入输出中,我们需要知道以什么为基准来定义输入、输出,我们所说的输入、输出是以cpu为基准来看待的。 

1.2绝对路径与相对路径

路径的含义:文件目录是树状结构,我们取到一个文件所经过的所有节点,就是这个文件的文件路径。

绝对路径:从根结点开始,一层一层向下找,经过的所有节点,就是绝对路径。

 相对路径:从给定的某个目录出发,一层一层向下找,经过的所有节点,就是相对路径。在相对路径时,我们需要明确基准目录是哪个。

1.3文本文件与二进制文件 

文本文件: 存储的文本遵守某些字符集编码(ASCII、utf8等),打开时,会通过对比字符集编码进行内容显示,就像我们打开文本文件时,我们都可以看懂是什么,在打开二进制文件时,内容就会出现乱码的情况(在字符集编码中无法找到相匹配的内容)。

二进制文件:二进制文件大大加大了存储的内容,它可以存储图片、音乐、视频,打开时以二进制的形式打开。

常见的文本文件(后缀):.txt、.java、.c等。

常见的二进制文件(后缀):.class、.exe、.jpg、.mp3、.docx等。

如何辨别二进制文件和文本文件? 

非常简单,我们只需打开记事本,把文件拉入到记事本中,不乱码就是文本文件,乱码就是二进制文件,如下图,打开.java文件没有出现乱码,打开.docx 文件就变成了乱码。

2.Java中操作文件 

在Java中,它给出了File类对文件进行操作。 

2.1File类

2.1.1构造方法 

签名说明
File(File parent, String
child)
根据父目录 + 孩子文件路径,创建一个新的 File 实例
File(String pathname)根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者
相对路径
File(String parent, String
child)
根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用
路径表示

2.1.2常用方法

修饰符及返回
值类型
方法签名说明
StringgetParent()返回 File 对象的父目录文件路径
StringgetName()返回 FIle 对象的纯文件名称
StringgetPath()返回 File 对象的文件路径
StringgetAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()判断 File 对象代表的文件是否是一个目录
booleanisFile()判断 File 对象代表的文件是否是一个普通文件
booleancreateNewFile()根据 File 对象,自动创建一个空文件。成功创建后返
回 true
booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()根据 File 对象,标注文件将被删除,删除动作会到
JVM 运行结束时才会进行
String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()返回 File 对象代表的目录下的所有文件,以 File 对象
表示
booleanmkdir()创建 File 对象代表的目录
booleanmkdirs()创建 File 对象代表的目录,如果必要,会创建中间目
booleanrenameTo(File
dest)
进行文件改名,也可以视为我们平时的剪切、粘贴操
booleancanRead()判断用户是否对文件有可读权限
booleancanWrite()判断用户是否对文件有可写权限

3.文件内容的读写

IO流体系如下,它分为两组,一组是字节流,一组是字符流,对于二进制文件进行文件内容读写可以使用InputStream(读)和OutputStream(写)操作,对于文本文件进行读写使用Reader(读)和Writer(写)进行操作,上方所说的四个类是抽象类,如果需要具体实现,我们需要实例化它的子类,通过子类完成任务。

我们下面对于字节流中的类进行详细讲解:

2.1输入流概述

 读文件时使用的方法

修饰符及
返回值类
方法签名说明
intread()读取一个字节的数据,返回 -1 代表已经完全读完了
intread(byte[] b)最多读取 b.length 字节的数据到 b 中,返回实际读到的数
量;-1 代表以及读完了
intread(byte[] b,
int off, int len)
最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返
回实际读到的数量;-1 代表以及读完了
voidclose()关闭字节流

在read()方法中,它的返回值是byte类型,但是为什么我们要使用int来接收呢?

用int类型来代替byte类型是为了解决读到结尾时出现难以辨别的情况,因为byte的取值范围是-128~127,当我们读到文件内容的末尾时,read()的返回值会是-1(文本内容也可能是-1),因为-1在buye的取值范围内,因此你不能确定它是文本内容还是到了文本结尾,而改为int,int的取值范围是0-255,返回-1,就很容易辨别是末尾了。

 2.1.1FileInputStream概述

该类是对字节流的读操作实现。 

构造方法

方法签名说明
FileInputStream(File file)利用 File 构造文件输入流
FileInputStream(String name)利用文件路径构造文件输入流

因为InputStream类是一个抽象类,我们想要使用,就要实例它的子类(FileInputStream)。

代码使用FileInputStream类:

import java.io.*;

public class ioDemo1 {
    
    public static void main(String[] args) {
        File file=new File("F:/test.txt");
        try(InputStream inputStream=new FileInputStream("F:/test.txt")) {
            while (true){
                int ret=inputStream.read();
                //返回-1,读到尾部
                if(ret==-1) {
                    break;
                }
                System.out.println(ret);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

代码运行结果(ASCII码):

2.1.2 FileReader概述

 该类是对字符流的读操作实现。

 构造方法

方法签名说明
FileReader(File file)创建一个新的 FileReader ,给出 File读取
FileReader(FileDescriptor fd)创建一个新的 FileReader ,给定 FileDescriptor读取。
FileReader(String fileName)创建一个新的 FileReader ,给定要读取的文件的名称。

 代码使用FileReader类:

import java.io.*;

public class ioDemo3 {
    public static void main(String[] args) {
        File file=new File("F:/test.txt");

        try(Reader reader=new FileReader("F:/test.txt")) {
            while (true) {
                int r = reader.read();
                if (r == -1) {
                    break;
                }
                System.out.print((char)r);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

代码运行结果:

观察得出,他是打印的字符,他是如何打印的呢?原理很简单,在读取数据时,系统会对比对照,我们设置什么字符集编码它就以什么字符集编码对比。 

2.3输出流概述

写文件时使用的方法

返回
值类
方法签名说明
voidwrite(int b)写入要给字节的数据
voidwrite(byte[]
b)
将 b 这个字符数组中的数据全部写入 os 中
intwrite(byte[]
b, int off,
int len)
将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
voidclose()关闭字节流
voidflush()重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为
了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的
一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写
入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的
数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,
调用 flush(刷新)操作,将数据刷到设备中。

2.3.1FileOutputStream概述

该类是字节流的写操作。

构造方法:

方法签名说明
FileOutputStream(File file)创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append)创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(FileDescriptor fdObj)

创建文件输出流以写入指定的文件描述符,

表示与文件系统中实际文件的现有连接。

FileOutputStream(String name)创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append)创建文件输出流以指定的名称写入文件。

  代码使用FileOutputStream类:

import java.io.*;

public class ioDemo4 {
    public static void main(String[] args) {
        try (OutputStream outputStream=new FileOutputStream("F:/test.txt") ){
            outputStream.write(1);
            outputStream.write(2);
            outputStream.write(3);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 代码会将1 2 3以二进制的形式写入到F:/test.txt这个目录中的test文件中。

 2.3.2FileWriter概述

 该类是字符流写操作

构造方法:

方法签名说明
FileWriter(File file)给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append)给一个File对象构造一个FileWriter对象。
FileWriter(FileDescriptor fd)构造与文件描述符关联的FileWriter对象。
FileWriter(String fileName)构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append)

构造一个FileWriter对象,给出一个

带有布尔值的文件名,表示是否附加写入的数据。

 代码使用FileWriter类:

import java.io.*;
public class ioDemo5 {
    /**
     * 文本写
     * @param args
     */
    public static void main(String[] args) {
        try(FileWriter fileWriter=new  FileWriter("F:/test.txt")){
            fileWriter.write(1);
            fileWriter.write(2);
            fileWriter.write("c");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 代码会以文本的形式将 1,2,c写入文件test中。

3.文件io小练习 

要求:扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class ioDemo2 {
    /**
     * 查询一个字符是否存在这个目录
     * @param args
     */
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        //1.输入搜索根目录
        System.out.println("输入需要找到扫描的路径");
        String findRootPath=sc.next();
        File findRoot=new File(findRootPath);
        if(!findRoot.isDirectory()) {
            System.out.println("您选择的不是路径,退出");
            return;
        }
        //2.输入需要查询的字符
        System.out.println("输入需要找的字符");
        String findStr=sc.next();
        //3.递归进行目录遍历
        scanDirWithContent(findRoot, findStr);
    }

    private static void scanDirWithContent(File findRoot, String findStr) {
        File[] files=findRoot.listFiles();
        if(files.length==0 || files==null) {
            return;
        }
        for (File file:files) {
            //是目录
            if(file.isDirectory()) {
                scanDirWithContent(file,findStr);
            //是文件
            }else if(file.isFile()) {
                String content=readFile(file);
                if(content.contains(findStr)) {
                    System.out.println(file.getAbsolutePath()+"包含字符");
                }
            //其他文件
            }else {
                continue;
            }
        }
    }

    /**
     * 找字符,对的拼接起来
     * @param file
     * @return
     */
    private static String readFile(File file) {
        StringBuilder sb=new StringBuilder();
        try(Reader reader=new FileReader(file)){
            while (true) {
                int read=reader.read();
                if(read==-1) {
                    break;
                }
                sb.append((char)read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}

写在最后:

🐣🐣🐣以上就是本文全部内容,如果对你有所帮助,希望能留下你的点赞+关注,我会更加努力的更新内容!非常感谢🧡🧡🧡

若本篇文章有错误的地方,欢迎大佬们指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱吃大白菜  

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

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

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

打赏作者

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

抵扣说明:

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

余额充值