[File operation and IO] How to operate files in Java

Table of contents

 Manipulating files in Java

File overview

Attributes

Construction method

method

code example

Read and write file content - data stream

 Overview of InputStreams

Overview of FileInputStream

Character reading with Scanner

Overview of OutputStreams

Write characters using OutputStreamWriter

Use PrintWriter to find our familiar methods

code reference

How to read data by byte

How to write data by byte

How to read data by character

How to write data by character


Manipulating files in  Java


An important function of the operating system is the management of files. Each operating system has its own set of system API calls. As a cross-platform language, Java has a layer of encapsulation for different operating systems. We only need to use The API for file operations provided by JDK can complete file operations on different systems.

In Java, a file (including a directory) is abstractly described through the java.io.File class. Note that having a File object does not mean that the file actually exists .

File overview

Attributes

modifiers and types 

Attributes

illustrate

static String

pathSeparator

System-dependent path separator, represented by String type

static char

pathSeparator

System-dependent path separator, char type representation

Construction method

method

modifiers and returns

value type

method signature

illustrate

String

getParent()

Returns the file path of the parent directory of the File object

String

getName()

Returns the plain file name of the FIle object

String

getPath()

Returns the file path of the File object

String

getAbsolutePath()

Returns the absolute path of the File object

String

getCanonicalPath()

Returns the decorated absolute path of the File object

boolean

exists()

Determine whether the file described by the File object actually exists

boolean

isDirectory()

Determine whether the file represented by the File object is a directory

boolean

isFile()

Determine whether the file represented by the File object is an ordinary file

boolean

createNewFile()

According to the File object, an empty file is automatically created. return after successful creation

times true

boolean

delete()

According to the File object, delete the file. Returns true after successful deletion

void

deleteOnExit()

According to the File object, the marked file will be deleted, and the delete action will go to

Only when the JVM finishes running

String[]

list()

Returns all file names under the directory represented by the File object

File[]

listFiles()

Return all files under the directory represented by the File object, and the File object

express

boolean

mkdir()

Create the directory represented by the File object

boolean

mkdirs()

Create the directory represented by the File object and, if necessary, intermediate

record

boolean

renameTo(File

dest)

Renaming files can also be regarded as our usual cut and paste operations.

do

boolean

canRead()

Determine whether the user has read permission on the file

boolean

canWrite()

Determine whether the user has writable permissions on the file

code example

Example 1

Observe the features and differences of the get series

import java.io.File;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        File file = new File("..\\hello-world.txt"); // 并不要求该文件真实存在
        System.out.println(file.getParent());
        System.out.println(file.getName());
        System.out.println(file.getPath());
        System.out.println(file.getAbsolutePath());
        System.out.println(file.getCanonicalPath());
   }
}

operation result

..
hello-world.txt
..\hello-world.txt
D:\代码练习\文件示例1\..\hello-world.txt
D:\代码练习\hello-world.txt

Example 2

Create and delete common files

import java.io.File;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        File file = new File("hello-world.txt"); // 要求该文件不存在,才能看到相同的现象
        System.out.println(file.exists());
        System.out.println(file.isDirectory());
        System.out.println(file.isFile());
        System.out.println(file.createNewFile());
        System.out.println(file.exists());
        System.out.println(file.isDirectory());
        System.out.println(file.isFile());
        System.out.println(file.createNewFile());
   }
}

operation result

false
false
false
true
true
false
true
false

Example 3

Observe the phenomenon of deleteOnExit

import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        File file = new File("some-file.txt"); // 要求该文件不存在,才能看到相同的现象
        System.out.println(file.exists());
        System.out.println(file.createNewFile());
        System.out.println(file.exists());
        file.deleteOnExit();
        System.out.println(file.exists());
   }
}

operation result

false
true
true
true

After the program finishes running, the file is still deleted

Example 4

Watch directory creation

import java.io.File;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        File dir = new File("some-parent\\some-dir"); // some-parent 和 somedir 都不存在
        System.out.println(dir.isDirectory());
        System.out.println(dir.isFile());
        System.out.println(dir.mkdir());
        System.out.println(dir.isDirectory());
        System.out.println(dir.isFile());
   }
}

operation result

false
false
false
false
false

When mkdir(), if the intermediate directory does not exist, it cannot be created successfully; mkdirs() can solve this problem.

import java.io.File;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        File dir = new File("some-parent\\some-dir"); // some-parent 和 somedir 都不存在
        System.out.println(dir.isDirectory());
        System.out.println(dir.isFile());
        System.out.println(dir.mkdirs());
        System.out.println(dir.isDirectory());
        System.out.println(dir.isFile());
   }
}

operation result

false
false
true
true
false

Example 5

Watch for file renaming

import java.io.File;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        File file = new File("some-file.txt"); // 要求 some-file.txt 得存在,可以是普通文件,可以是目录
        File dest = new File("dest.txt");   // 要求 dest.txt 不存在
        System.out.println(file.exists());
        System.out.println(dest.exists());
        System.out.println(file.renameTo(dest));
        System.out.println(file.exists());
        System.out.println(dest.exists());
   }
}

operation result

true
false
true
false
true

Reading and writing of file content - data flow


Data Flow Classification

 InputStream overview

method

modifiers and
return value class
type
method signature
illustrate
int
read()
Read a byte of data, return -1 means it has been completely read
int
read(byte[] b)
最多读取 b.length 字节的数据到 b 中,返回实际读到的数
量; -1 代表以及读完了
int
read(byte[] b,
int off, int len)
最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返
回实际读到的数量; -1 代表以及读完了
void
close()
关闭字节流

说明

InputStream 只是一个抽象类,要使用还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,我们现在只关心从文件中读取,所以使用 FileInputStream

FileInputStream 概述

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

示例

这里我们把文件内容中填充中文看看,注意,写中文的时候使用 UTF-8 编码。hello.txt 中填写 "你好中国"

注意:这里我利用了这几个中文的 UTF-8 编码后长度刚好是 3 个字节和长度不超过 1024 字节的现状,但这种方式并不是通用的

import java.io.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容
public class Main {
    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("hello.txt")) {
            byte[] buf = new byte[1024];
            int len;
            while (true) {
                len = is.read(buf);
                if (len == -1) {
                    // 代表文件已经全部读完
                    break;
               }
                // 每次使用 3 字节进行 utf-8 解码,得到中文字符
                // 利用 String 中的构造方法完成
                // 这个方法了解下即可,不是通用的解决办法
                for (int i = 0; i < len; i += 3) {
                    String s = new String(buf, i, 3, "UTF-8");
                    System.out.printf("%s", s);
               }
           }
       }
   }
}

利用 Scanner 进行字符读取

上述例子中,我们看到了对字符类型直接使用 InputStream 进行读取是非常麻烦且困难的,所以,我们使用一种我们之前比较熟悉的类来完成该工作,就是 Scanner 类。

构造方法
说明
Scanner(InputStream is, String charset)
使用 charset 字符集进行 is 的扫描读取
示例
import java.io.*;
import java.util.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容
public class Main {
    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("hello.txt")) {
           try (Scanner scanner = new Scanner(is, "UTF-8")) {
               while (scanner.hasNext()) {
                   String s = scanner.next();
                   System.out.print(s);
               }
           }
       }
   }
}

OutputStream 概述

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

说明

OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中,所以使用 FileOutputStream

利用 OutputStreamWriter 进行字符写入

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            String s = "你好中国";
            byte[] b = s.getBytes("utf-8");
            os.write(b);
            // 不要忘记 flush
            os.flush();
       }
   }
}

利用 PrintWriter 找到我们熟悉的方法

上述,我们其实已经完成输出工作,但总是有所不方便,我们接来下将 OutputStream 处理下,使用PrintWriter 类来完成输出,因为

PrintWriter 类中提供了我们熟悉的 print/println/printf 方法
import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("output.txt")) {
            try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8")) {
                try (PrintWriter writer = new PrintWriter(osWriter)) {
                    writer.println("我是第一行");
                    writer.print("我的第二行\r\n");
                    writer.printf("%d: 我的第三行\r\n", 1 + 1);
                    writer.flush();
               }
           }
       }
   }
}

代码参考


如何按字节进行数据读

try (InputStream is = ...) {
    byte[] buf = new byte[1024];
    while (true) {
        int n = is.read(buf);
        if (n == -1) {
            break;
       }
        // buf 的 [0, n) 表示读到的数据,按业务进行处理
   }
}

如何按字节进行数据写

try (OutputStream os = ...) {
    byte[] buf = new byte[1024];
    while (/* 还有未完成的业务数据 */) {
        // 将业务数据填入 buf 中,长度为 n
        int n = ...;
        os.write(buf, 0, n);
   }
    os.flush(); // 进行数据刷新操作
}

如何按字符进行数据读

try (InputStream is = ...) {
    try (Scanner scanner = new Scanner(is, "UTF-8")) {
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            // 根据 line 做业务处理
       }
   }
}

如何按字符进行数据写

try (OutputStream os = ...) {
    try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8")) {
        try (PrintWriter writer = new PrintWriter(osWriter)) {
            while (/* 还有未完成的业务数据 */) {
                writer.println(...);
           }
            writer.flush(); // 进行数据刷新操作
       }
   }
}

Guess you like

Origin blog.csdn.net/m0_59952648/article/details/131278030