简单易懂讲文件

Posted Cyrus_sss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单易懂讲文件相关的知识,希望对你有一定的参考价值。

注意事项

如果运行代码的时候找不到文件,但是文件的的确确又存在,检查下 idea 的工作路径

路径

Path

Path 对象是将一个路径封装成一个对象,然后通过这个对象来执行路径的一些操作,所有的方法如下。具体的方法功能通过名称也能猜得八九不离十,不了解的查 API 文档。所有下面的方法都可以通过 idea 进入对应的类点击 alt + 7 查看

Paths

获取 Path 对象的工具类,一共两个重载方法

  • Path get(String first, String... more) 允许接收一个或者多个字符串,从而构造出一个 Path 对象
  • Path get(URI uri) 允许接收一个 uri 对象,从而构造出一个 Path 对象
import java.nio.file.Path;
import java.nio.file.Paths;

class PathDemo {
    public static void demo() {
        // 重载方法一,允许接受一个或者多个参数
        Path path1 = Paths.get("Main.java");
        System.out.println(path1.toAbsolutePath());
        Path path2 = Paths.get("E","1.base","workspace","slime");
        System.out.println(path2.toAbsolutePath());
        // 重载方法二,允许接受一个 URI 对象
        Path urlPath = Paths.get(path1.toUri());
        System.out.println(urlPath.toAbsolutePath());
    }
}

public class Main {
    public static void main(String[] args) {
        PathDemo.demo();
    }
}

输出:

E:\\1.base\\workspace\\slime\\file_io\\src\\main\\java\\cyrus\\file_io\\file\\Main.java
E:\\1.base\\workspace\\slime\\file_io\\src\\main\\java\\cyrus\\file_io\\file\\E\\1.base\\workspace\\slime
E:\\1.base\\workspace\\slime\\file_io\\src\\main\\java\\cyrus\\file_io\\file\\Main.java

文件

File

文件是将文件构造成一个 File 对象,然后通过操作这个对象来对文件进行读取,新增,更新,删除等操作。具体 API 如下,根据名字也能猜个七八分,具体 API 用法可以查看 API 文档。

Files 对象

Files 对象可以操作对象路径下的文件,也可以操作这个路径,这里的路径是被包装成 Path 对象的。

文件查找

通过 FileSystems 类来进行文件查找,例子如下:

在 matcher 中,glob 表达式开头的 **/ 表示“当前目录及所有子目录”,这在当你不仅仅要匹配当前目录下特定结尾的 Path 时非常有用。单 * 表示“任何东西”,然后是一个点,然后大括号表示一系列的可能性---我们正在寻找以 .tmp 或 .txt 结尾的东西。您可以在 getPathMatcher() 文档中找到更多详细信息。

class Find {
    public static void demo() {
        Path test = Paths.get("test");
        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.{temp,txt}");
        try {
            Files.walk(test).filter(matcher::matches).forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Find.demo();
    }
}

输出:

test\\123.temp
test\\dsaioh.txt
test\\test\\345.temp
test\\test\\qwe.txt

文件读写

读取

使用 Files 工具类进行操作,以下例子使用 readAllLines(Path path) 方法将整个 Main.java 文件读取并且打印到控制行中。

public class Main {
    public static void main(String[] args) throws IOException {
        List<String> list = Files.readAllLines(Paths.get("Main.java"));
        list.stream().forEach(System.out::println);
    }
}

输出:

package cyrus.file_io.file;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;


public class Main {
    public static void main(String[] args) throws IOException {
        List<String> list = Files.readAllLines(Paths.get("Main.java"));
        list.stream().forEach(System.out::println);
    }
}

写入

这里先创建个文件 1.txt 然后通过 Path write() 方法写入文档,该方法需要一个路径 Path 以及写入的 byte 数组

public class Main {
    public static void main(String[] args) throws IOException {

        File file = new File("test" + File.separator + "test" + File.separator + "1.txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        String str = "input something";
        Files.write(file.toPath(), str.getBytes());
    }
}

输出:

文件太大怎么办

读取

通过 Files.lines() 将文件一行一行读取,每一行都是一个 Stream 流。

public class Main {
    public static void main(String[] args) throws IOException {
        Stream<String> lines = Files.lines(Paths.get("Main.java"));
        lines.forEach(System.out::println);
    }
}

输出:

package cyrus.file_io.file;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Stream;


public class Main {
    public static void main(String[] args) throws IOException {
        Stream<String> lines = Files.lines(Paths.get("Main.java"));
        lines.forEach(System.out::println);
    }
}

写入

也是先通过Files.lines() 将文件一行一行读取,然后一行行写入

public class Main {
    public static void main(String[] args) throws IOException {
        String name = "test" + File.separator + "test" + File.separator + "Main.txt";
        PrintWriter printWriter = new PrintWriter(name);
        Files.lines(Paths.get("Main.java")).forEach(printWriter::println);
        printWriter.close();
    }
}

输出:

文章为本人学习过程中的一些个人见解,漏洞是必不可少的,希望各位大佬多多指教,帮忙修复修复漏洞!!!

进入本人语雀文档体验更好哦
https://www.yuque.com/docs/share/e91bfe3d-1d76-4ef2-99a5-543d79e20c38?# 《文件》
参考资料:java 编程思想

你可能还想阅读以下文章:
简单易懂讲IO

简单易懂讲IO

流式 IO 是传统 IO,通过构造输入输出流,讲信息从一个地方读取,输出到另一个地方。常见的有读取文件以及写入文件。

基本 API

流失 IO 基本可以分为两个门派,一个以 InputStream 和 OutputStream 为代表的老牌 IO,一个以 Reader 和 Writer 为代表的新派 IO。

这里仅仅展示最常用 API,其余 API 可以查阅 jdk API

输入

基本输入

InputStream Reader
InputStream 面向字节流 IO 不能很好的支持 Unicode 字符 Reader 面向字符流 IO 能很好的支持 Unicode 字符
FileInputStream 文件读取流 FileReader 文件读取
ByteArrayInputStream CharArrayReader

装饰器输入

基本输入中的流对象,都可以作为装饰器对象的构造器参数

InputStream Reader 功能
DataInputStream 包含用于读取基本数据类型的全部接口
BufferedInputStream BufferedReader 本质上不提供接口,只是向进程添加缓冲功能。与接口对象搭配

输出

基本输出

OutputStream Writer
FileOutputStream FileWriter
ByteArrayOutputStream CharArrayWriter

装饰器输出

OutputStream Writer 功能
DataOutputStream 包含用于写入基本数据类型的全部接口
PrintStream PrintWriter 用于产生格式化输出
BufferedOutputStream BufferedWriter 本质上并不提供接口,只是向进程添加缓冲功能。与接口对象搭配

常见用法

读取文件

使用 FileInputStream 读取

下面例子将输入流放入 try-with-resource 块中,以实现资源的自动关闭,本文下面例子都将采用这种形式。

这里可以看到,是一个字节一个字节的读,所以要将其转为 char 才能正常展示,否则展示的都是字节。 由于 InputStream 是字节流,因此,这里读取到的中文展示乱码。

public class Read {
    /**
     * 使用 FileInputStream 直接读取
     * 由于 InputStream 不支持 Unicode 编码,所以中文显示会乱码
     */
    public static void fileInputStream() {
        try (
                FileInputStream input = new FileInputStream("Read.java")
        ) {
            int n = 0;
            while (n != -1) {
                n = input.read();
                char c = (char) n;
                System.out.print(c);
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileInputStream();
    }
}

输出:

package cyrus.file_io.iostream;

import java.io.FileInputStream;

public class Read {
    /**
     * 使用 FileInputStream 直接读取
     * 由于 InputStream 不支持 Unicode ç¼–ç ï¼Œæ‰€ä»¥ä¸­æ–‡æ˜¾ç¤ºä¼šä¹±ç 
     */
    public static void fileInputStream() {
        try (
                FileInputStream input = new FileInputStream("Read.java")
        ) {
            int n = 0;
            while (n != -1) {
                n = input.read();
                char c = (char) n;
                System.out.print(c);
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileInputStream();
    }
}

使用 BufferedInputStream 装饰器读取

以下例子使用 FileInputStream 构造一个 BufferedInputStream 装饰器,该适配器的主要作用是会将读取到的内容填充进缓冲区,其余用法和 FileInputStream 一样。InputStream 是字节流,因此,这里读取到的中文展示乱码。

public class Read {
    /**
     * 使用 FileInputStream 构造一个 BufferedInputStream 装饰器,读取,该读取会使用缓冲区
     * 由于 InputStream 不支持 Unicode 编码,所以中文会乱码
     */
    public static void fileInputStreamWithBuffer() {
        try (
                BufferedInputStream input = new BufferedInputStream(new FileInputStream("Read.java"))
        ) {
            int n = 0;
            while (n != -1) {
                n = input.read();
                char c = (char) n;
                System.out.print(c);
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileInputStreamWithBuffer();
    }
}

输出:

package cyrus.file_io.iostream;

import java.io.BufferedInputStream;
import java.io.FileInputStream;

public class Read {
    /**
     * 使用 FileInputStream æž„é€ ä¸€ä¸ª BufferedInputStream 装饰器,读取,该读取会使用缓冲区
     * 由于 InputStream 不支持 Unicode ç¼–ç ï¼Œæ‰€ä»¥ä¸­æ–‡ä¼šä¹±ç 
     */
    public static void fileInputStreamWithBuffer() {
        try (
                BufferedInputStream input = new BufferedInputStream(new FileInputStream("Read.java"))
        ) {
            int n = 0;
            while (n != -1) {
                n = input.read();
                char c = (char) n;
                System.out.print(c);
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileInputStreamWithBuffer();
    }
}

使用 FileReader 进行读取

使用 FileReader 直接读取,这里 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示

public class Read {
    /**
     * 使用 FileReader 直接读取
     * 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
     */
    public static void fileReader() {
        try (
                FileReader reader = new FileReader("Read.java")
        ) {
            int n = 0;
            while (n != -1) {
                n = reader.read();
                char c = (char) n;
                System.out.print(c);
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileReader();
    }
}

输出:

package cyrus.file_io.iostream;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileReader;

public class Read {
    /**
     * 使用 FileReader 直接读取
     * 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
     */
    public static void fileReader() {
        try (
                FileReader reader = new FileReader("Read.java")
        ) {
            int n = 0;
            while (n != -1) {
                n = reader.read();
                char c = (char) n;
                System.out.print(c);
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileReader();
    }
}

使用 BufferedReader 装饰器读取

这里使用 FileReader 构造一个 BufferedReader 装饰器,BufferedReader 的主要作用是会将读取到的内容填入缓冲区,并且 BufferedReader 的 lines() 方法将返回一个 stream 流,操作更方便。

public class Read {
    /**
     * 使用 FileReader 构造一个 BufferedReader 装饰器,读取,该读取会使用缓冲区
     * 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
     */
    public static void fileReaderWithBuffer() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            reader.lines().forEach(System.out::println);
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileReaderWithBuffer();
    }
}

输出:

package cyrus.file_io.iostream;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;

public class Read {
    /**
     * 使用 FileReader 构造一个 BufferedReader 装饰器,读取,该读取会使用缓冲区
     * 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
     */
    public static void fileReaderWithBuffer() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            reader.lines().forEach(System.out::println);
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) {
        Read.fileReaderWithBuffer();
    }
}

使用 DataInputStream 适配器读取字符串

这里 buildString() 方法读取当前文件,将其拼装为字符串输出,ByteArrayInputStream 读取该字符串的 byte 数组,然后转化为 DataInputStream 适配器进行读取字符串内容。

DataInputStream 主要用于读取基本数据类型

public class Read {
    /**
     * 使用 ByteArrayInputStream 构造 DataInputStream 装饰器,输出字符串信息
     */
    public static void dataInputStream() {
        try (
                DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(buildString().getBytes()))
        ) {
            while (inputStream.available() != 0) {
                System.out.print((char) inputStream.readByte());
            }
        } catch (Exception e) {

        }
    }

    /**
     * 通过目前 java 文件构建一个字符串
     *
     * @return
     */
    public static String buildString() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            return reader.lines().collect(Collectors.joining("\\n"));
        } catch (Exception e) {

        }
        return "ok";
    }

    public static void main(String[] args) {
        Read.dataInputStream();
    }
}

写入文件

使用 FileOutputStream 写入

这里直接使用 FileOutputStream 读取 buildString() 方法构造的字符串并将其写入 Read.txt 文件

public class Read {
    /**
     * 使用 FileOutputStream 直接写入字符串
     */
    public static void fileOutputStream() {
        try (
                FileOutputStream output = new FileOutputStream("Read.txt")
        ) {
            output.write(buildString().getBytes());
        } catch (Exception e) {

        }
    }
    /**
     * 通过目前 java 文件构建一个字符串
     *
     * @return
     */
    public static String buildString() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            return reader.lines().collect(Collectors.joining("\\n"));
        } catch (Exception e) {

        }
        return "ok";
    }

    public static void main(String[] args) {
        Read.fileOutputStream();
    }
}

输出:实例截图一部分

使用 BufferedOutputStream 适配器写入

这里使用 FileOutputStream 构造一个 BufferedOutputStream 适配器,BufferedOutputStream 会使用到缓冲区,加快读取写入速度。

public class Read {
    /**
     * 使用 FileOutputStream 构造一个 BufferedOutputStream 装饰器,读取,该写入会使用缓冲区
     */
    public static void fileOutputStreamWithBuffer() {
        try (
                BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("Read.txt"));
        ) {
            output.write(buildString().getBytes());
        } catch (Exception e) {

        }
    }
    /**
     * 通过目前 java 文件构建一个字符串
     *
     * @return
     */
    public static String buildString() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            return reader.lines().collect(Collectors.joining("\\n"));
        } catch (Exception e) {

        }
        return "ok";
    }

    public static void main(String[] args) {
        Read.fileOutputStreamWithBuffer();
    }
}

后面就不展示输出了,所有的输出都是输出到当前工作目录的Read.txt文件夹下,并且文件内容都是当前 .java 文件的内容

使用 FileWriter 写入

public class Read {
    /**
     * 使用 FileWriter 直接写入
     */
    public static void fileWriter() {
        try (
                FileWriter writer = new FileWriter("Read.txt");
        ) {
            writer.write(buildString());
        } catch (Exception e) {

        }
    }
    /**
     * 通过目前 java 文件构建一个字符串
     *
     * @return
     */
    public static String buildString() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            return reader.lines().collect(Collectors.joining("\\n"));
        } catch (Exception e) {

        }
        return "ok";
    }

    public static void main(String[] args) {
        Read.fileWriter();
    }
}

使用 PrintWriter 进行输出

这里使用了两层适配器,第一层是使用 FileWriter 构造一个 BufferedWriter,该适配器会使用缓冲区进行写入,然后再使用 BufferedWriter 构造一个PrintWriter 适配器,使用该适配器的println()方法直接输出到指定文件。

public class Read {
    /**
     * 使用 FileWriter 构造一个 BufferedWriter 装饰器,该装饰器会使用缓冲区,然后再使用 BufferedWriter 构造一个 PrintWriter装饰器,使用 println 输出到文件
     */
    public static void fileWriterWithBuffer() {
        try (
                PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("Read.txt")))
        ) {
            writer.println(buildString());
        } catch (Exception e) {

        }
    }
    /**
     * 通过目前 java 文件构建一个字符串
     *
     * @return
     */
    public static String buildString() {
        try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
            return reader.lines().collect(Collectors.joining("\\n"));
        } catch (Exception e) {

        }
        return "ok";
    }

    public static void main(String[] args) {
        Read.fileWriterWithBuffer();
    }
}

总结

流式IO 其实挺好理解的,一共分为两套,InputStream、OutputStream 为一套,Reader 和 Writer 为一套,其中各自都有基本输入输出类和使用基本输入输出类构造的装饰器输入输出类,装饰器还能构造装饰器,无限套娃。

如 new PrintWriter(new BufferedWriter(new FileWriter("Read.txt"))),这里就将 BufferedWriter 装饰器装配成了 PrintWriter 装饰器,这样这个 PrintWriter 就拥有了 BufferedWriter 的特性(使用缓冲区),以及他自己的特性。

文章为本人学习过程中的一些个人见解,漏洞是必不可少的,希望各位大佬多多指教,帮忙修复修复漏洞!!!

参考资料:java 编程思想
欢迎进入本人语雀文档阅读,格式更清晰哦:

https://www.yuque.com/docs/share/26bf2f91-b3d3-4b28-a43e-302a1e650d57?# 《流式 IO》

以上是关于简单易懂讲文件的主要内容,如果未能解决你的问题,请参考以下文章

五子棋游戏(简单易懂,入门都能学)

创建自己的代码片段(CodeSnippet)

求java 的queue 和dequeue 的意思(简单易懂)能帮我讲明白吗

编程思想与算法

如何用简单易懂的例子解释隐马尔可夫模型?

常用编程思想与算法