Java 基础之文件处理

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1. Stream 流

2. File 和 IO

Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标

2.1 控制台输入

Java 的控制台输入由 System.in 完成 将 System.in 包装在一个 BufferedReader 对象中来创建一个字符流创建后可使用 read() 方法读取一个 字符读取字符串使用 readLine()

import java.io.*;

public class BufferedReaderTest {
    public static void main(String[] args) throws IOException {
        char c;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("输入字符按 'q' 退出");
        do {
            // 读取字符
            c = (char) br.read();   // 每次只能读取一个字符
            System.out.println(c);
        } while (c != 'q');
    }
}

输出

输入字符按 'q' 退出
a
a

b
b

c
c

java
j
a
v
a

q
q

注意read() 方法读取一个字符就会返回一个整数直至输入流结束返回 -1此时会抛出 IOException因此要 throws

2.2 控制台输出

控制台的输出可以由 print() 和 println() 、write() 完成都是来自 PrintStream 类不过 write() 方法不常用

// void write(int byteval)write() 方法将 byteval 的低八位字节写到流中
System.out.println("abc");
int b;
b = 'A';
System.out.write(b);
System.out.write('\n');

2.3 文件读写

输入流和输出流的类层次图

2.3.1 FileInputStream

该流用于读取文件数据创建方法

// 方法一
InputStream f = new FileInputStream("xxx.txt");

// 方法二
File f = new File("xxx.txt");
InputStream in = new FileInputStream(f);

文件对象常用方法

方法描述
public void close() throws IOException{}关闭文件输入流并释放与此流相关的所有系统资源抛出 IOException
protected void finalize()throws IOException {}清除与该文件的连接确保在不引用时调用 close() 方法抛出 IOException
public int read(int r)throws IOException{}从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据如果已经到结尾则返回-1
public int read(byte[] r) throws IOException{}从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1
public int available() throws IOException{}返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FileInputStreamTest {
    public static void main(String[] args) throws IOException {
        readFile();
    }

    public static void readFile() throws IOException {
        int name;
        // 创建文件对象
        InputStream input = new FileInputStream("F:\\JavaStudy\\Source\\FileTest\\src\\people.txt");
        do {
            name = input.read(); // 循环调用 read()直至返回 -1
            System.out.println(name);
        } while (name != -1);   // name = -1 时文件读取完毕

        input.close();  // 关闭
    }
}

运行结果

114
111
115
101
13
10
108
105
108
97
13
10
106
111
104
110
-1

read() 方法每次只会读取一个字节直至读取完毕返回 -1可以根据此来作为循环退出条件另外需要记得关闭文件对象

使用 for 循环读取

public static void readFile() throws IOException {
        int name;
        // 创建文件对象
        InputStream input = new FileInputStream("F:\\JavaStudy\\Source\\FileTest\\src\\people.txt");
//        do {
//            name = input.read(); // 循环调用 read()直至返回 -1
//            System.out.println(name);
//        } while (name != -1);

        for (; ; ) {
            name = input.read(); // 循环调用 read()直至返回 -1
            if (name == -1) {
                break;
            }
            System.out.println(name);
        }

        input.close();  // 关闭
    }

使用 try...finally 保证任何时候都会关闭文件对象

public static void readFileTest() throws IOException {
        InputStream input = null;
        try {
            input = new FileInputStream("F:\\JavaStudy\\Source\\FileTest\\src\\people.txt");
            int n = 0;
            while (n != -1) {
                n = input.read();
                System.out.println(n);
            }
        } finally {
            if (input != null) {
                input.close();
            }
        }
    }

Java7 后省略写法

public void readFile() throws IOException {
    try (InputStream input = new FileInputStream("F:\\JavaStudy\\Source\\FileTest\\src\\people.txt")) {
        int n;
        while ((n = input.read()) != -1) {
            System.out.println(n);
        }
    } // 编译器在此自动为我们写入finally并调用close()
}

缓冲一次读取多个字节

read() 方法只能一次读取一个字节但是可以将读取的字节放入一个缓冲的 bytes[] 数组中这样返回值不再是字节的 int 值而是返回实际读取了多少个字节。如果返回-1表示没有更多的数据了

public static void readFileCache() throws IOException {
        try (InputStream input = new FileInputStream("F:\\JavaStudy\\Source\\FileTest\\src\\people.txt")) {
//            定义 1000 个字节大小的缓冲区
            byte[] buffer = new byte[1000];
            int n;
            while ((n = input.read(buffer)) != -1) {
                System.out.println("已读取" + n + " 字节");     // 已读取16 字节
            }
        }
    }

2.3.2 FileOutputStream

FileOutputStream 用来创建一个文件并向文件中写数据若目标文件不存在那么该流会创建该文件

// 方法一
OutputStream f = new FileOutputStream("C:/java/hello")

// 方法二
File f = new File("C:/java/hello");
OutputStream fOut = new FileOutputStream(f);

常用方法

方法说明
close()关闭文件对象释放系统资源
finalize()清除与该文件的连接确保在不再引用文件输入流时调用其 close 方法。抛出 IOException 异常
write(int w)将指定的字节写入到输出流中
write(byte[] w)将指定数组中的 w.length 长度的字节写入到输出流中
flush()将缓冲区内容写入输出流中

flush()

当向磁盘、网络写入数据时并不是输出一个字节就立即写入而是先把输出存入内存中相当于缓冲区当到达一定量后缓冲区满了再写入磁盘或网络这能提高写入效率减少 IO 消耗flush() 可以强制将缓冲区内容输出一般情况下我们不需要手动去 flush会自动 flush除非一些特殊情况需要比如缓冲区大小 4K但是输出的字节大小不足 4k这是就需要手动去 flush()

一次写入多个字节 xx.getBytes() 转换为 byte[]

public static void writeFile() throws IOException {
    try (OutputStream output = new FileOutputStream("F:\\JavaStudy\\Source\\FileTest\\src\\result.txt")) {
        output.write("Hello".getBytes("UTF-8"));
    }
}

2.4 File 类

关于文件和 IO 的类

  • File
  • FileReader
  • FileWriter

创建目录

File 类中两个方法

  • mkdir()创建一个目录成功返回 true否则返回 false表示指定的路径已存在或整个路径不存在
  • mkdirs()递归创建目录多个
import java.io.File;

public class FileTest {
    public static void main(String[] args) {
        String path = "F:\\JavaStudy\\Source\\FileTest\\src\\newFile";
        File d = new File(path);
        d.mkdir();
    }
}

读取目录

  • isDirectory()是否是一个目录是返回 true
  • list()返回目标目录中所有文件夹和文件
import java.io.File;

public class FileTest {
    public static void main(String[] args) {
        String path = "F:\\JavaStudy\\Source\\FileTest\\src";
        File f1 = new File(path);
        if (f1.isDirectory()) {
            System.out.println(path + " 是一个目录");
            String[] file_arrs = f1.list();
            for (int i = 0; i < file_arrs.length; i++) {
                File f2 = new File(file_arrs[i]);
                if (f2.isDirectory()) {
                    System.out.println(file_arrs[i] + " 是一个目录");
                } else {
                    System.out.println(file_arrs[i] + " 是一个文件");
                }
            }
        } else {
            System.out.println(path + " 是一个文件");
        }
    }
}

运行结果

F:\JavaStudy\Source\FileTest\src 是一个目录
BufferedReaderTest.java 是一个文件
FileInputStreamTest.java 是一个文件
FileTest.java 是一个文件
newFile 是一个文件
people.txt 是一个文件
result.txt 是一个文件

删除文件或目录

delete() 方法删除目录时需保证该目录下没有其他文件否则会删除失败

import java.io.File;

public class FileTest {
    public static void main(String[] args) {
//        删除目录或文件
        deleteDirectoryOrFile();

    }

    public static void deleteDirectoryOrFile() {
        String path = "F:\\JavaStudy\\Source\\FileTest\\src\\newFile";
        File f1 = new File(path);
//        直接删除失败
//        f1.delete();

        deleteDirectory(f1);
    }

    public static void deleteDirectory(File f1) {
        File[] files = f1.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    deleteDirectory(f);
                } else {
                    f.delete();
                }
            }
        }
        f1.delete();
    }
}

其他方法

canRead()  // 是否可读
canWrite() // 是否可写
canExecute()    // 是否可执行
length()    // 文件字节大小
listFiles() // 列出目录下的文件和子目录名

2.5 Path 类

Path 类与 File 类功能相似但操作更简单位于 java.nio.file 包中

public static void getPath() {
        Path p1 = Paths.get(".", "project", "java_study");  // 构造一个Path对象
        System.out.println(p1); //  .\project\java_study

        // 转换为绝对路径 F:\JavaStudy\Source\.\project\java_study
        Path p2 = p1.toAbsolutePath();
        System.out.println(p2);

        // 转换为规范路径 F:\JavaStudy\Source\project\java_study
        Path p3 = p2.normalize();
        System.out.println(p3);

        // 转换为File对象  F:\JavaStudy\Source\project\java_study
        File f = p3.toFile();
        System.out.println(f);

        // 遍历Path
        for (Path p: Paths.get("..").toAbsolutePath()) {
            System.out.println("===>" + p);
            
            /*
            ===>JavaStudy
            ===>Source
            ===>..
             */
        }
    }

2.6 Scanner 类

Scanner 类可以获得用户输入

Scanner scan = new Scanner(System.in);

常用方法

  • next()、nextLine()获取输入的字符串
  • hasNext()、hasNextLine()是否还有数据输入
  • nextInt()、nextFloat()接收数字

2.6.1 接收字符串

next 方法

import java.util.Scanner;


public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        System.out.println("请输入");
        if (scan.hasNext()) {
            String str1 = scan.next();
            System.out.println(str1);
        }
        scan.close();
    }
}

运行结果

请输入
Hello World			// 输入的字符串
Hello				// 只输出了 Hello没有输出 World

nextLine()

import java.util.Scanner;


public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        System.out.println("请输入");
        if (scan.hasNextLine()) {
            String str2 = scan.nextLine();
            System.out.println(str2);
        }
        scan.close();
    }
}

运行结果

请输入
Hello World
Hello World

next() 与 nextLine() 区别

  • next()
    • 对录入的字符串遇到 空格就会停止录入会截断空格后的字符串
    • 在录入字符串时会在尾部加一个 \r\nnextnextLine 之前录入就会导致 nextLine 录入了 \r\n
  • nextLine()
    • 会把整行字符串全部录入录入字符串时推荐使用
    • 回车为结束符可获得空白

2.6.2 接收数字

import java.util.Scanner;


public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int m = 0;
        float n = 0;
        System.out.println("请输入一个整数");
        if (scan.hasNextInt()) {
            m = scan.nextInt();
            System.out.println(m);
        }

        System.out.println("请输入一个小数");
        if (scan.hasNextFloat()) {
            n = scan.nextFloat();
            System.out.println(n);
        }
        scan.close();
    }
}

运行结果

请输入一个整数
36000
36000
请输入一个小数
3.6
3.6

2.6.3 示例

接收多个输入并求和

import java.util.Scanner;


public class ScannerTest {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        // 求和
        int a = 0;
        System.out.println("请输入一个整数输入非整数结束程序运行");
        while (scan.hasNextInt()) {
            a = a + scan.nextInt();
            System.out.println("请继续输入");
        }
        System.out.println("总和" + a);
        scan.close();
    }
}

运行结果

请输入一个整数输入非整数结束程序运行
1
请继续输入
2
请继续输入
3
请继续输入
4
请继续输入
a
总和10

2.6.4 接收文件流

Scanner sc=new Scanner(new File("test.txt"));
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;

public class ScannerFileTest {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner scan = new Scanner(new File("F:\\JavaStudy\\Source\\FileTest\\src\\people.txt"));
        while (scan.hasNextLine()) {
            System.out.println("接收到一个字符串" + scan.nextLine());
        }
    }
}

运行结果

接收到一个字符串rose
接收到一个字符串lila
接收到一个字符串john
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java