> 文章列表 > Java中的文件操作

Java中的文件操作

Java中的文件操作

Java中通过java.io.File类对一个文件(包含目录)进行抽象的描述。注意有File对象,并不代表真实存在该文件。

1.File概述

我们先看看File类中的常见属性、构造方法和方法

1.1属性

修饰符及类型 属性 说明
static String pathSeparator 依赖系统的路径分隔符,String类型的表示
static char pathSeparator 依赖系统的路径分隔符,char类型的表示

1.2构造方法

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

1.3方法

修饰符及返回类型 方法签名 说明
String getParent() 返回File对象的父目录文件路径
String getName() 返回File对象的纯文件名称
String getPath() 返回File对象的文件路径                
String getAbsolutePath() 返回File对象的绝对路径
String getCanonicalPath() 返回File对象的修饰过的绝对的路径
boolean exists() 判断File对象描述的文件是否真实存在
boolean isDirectory() 判断File对象代表的文件是否是一个目录
boolean isFile() 判断File对象代表的文件是否是一个普通文件
boolean createNewFile() 根据File对象,自动创建一个空文件。成功后返回true
boolean delete() 根据File对象,删除该文件。
String[] list() 返回File对象代表的目录下所有的文件名
File[] listFiles() 返回File对象代表的目录下的所有文件
boolean mkdir() 创建File对象代表的目录
boolean mkdirs() 创建File对象代表的目录,如果有必要,会创建中间目录
boolean renameTo(File dest) 进行文件改名,也可以十位我们平时的剪切、粘贴操作
boolean canRean() 判断用户是否对文件有可读权限
boolean canWrite() 判断用户是否对文件有可写权限

1.4代码示例

示例一get系列的特点和差异

import java.io.File;
import java.io.IOException;/*** Describe:获取文件的相关属性* User:lenovo* Date:2023-04-09* Time:16:51*/
public class TestDemo1 {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());}
}

 【示例二】普通文件的创建

import java.io.File;
import java.io.IOException;public class TestDemo2 {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());}
}

 【示例三普通文件的删除

import java.io.File;
import java.io.IOException;/*** Describe:普通文件的删除* User:lenovo* Date:2023-04-09* Time:17:12*/
public class TestDemo3 {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());System.out.println(file.delete());System.out.println(file.exists());}
}

示例四观察目录的创建

public class TestDemo4 {public static void main(String[] args) {File dir = new File("some-dir");//要求目录不存在System.out.println(dir.isDirectory());System.out.println(dir.isFile());System.out.println(dir.mkdir());System.out.println(dir.isDirectory());}
}

 

 【示例五创建多层目录

public class TestDemo5 {public static void main(String[] args) {File dir = new File("some-parent\\\\some-dir");//两个文件夹都必须不存在System.out.println(dir.isDirectory());System.out.println(dir.isFile());System.out.println(dir.mkdirs());System.out.println(dir.isDirectory());}
}

示例六观察文件重命名

public class TestDemo6 {public static void main(String[] args) {File file = new File("some-parent.txt");//要求文件存在File dest = new File("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());}
}

2.文件内容的读写——数据流

2.1InputStream概述

【方法】

修饰符及返回类型 方法签名 说明
int read() 读取一个字节的数据,返回-1代表已经完全读完了
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的实现类有很多。基本可以认为不同的输入设备对应一个InputSteam类,我们现在只关心从文件中读取,所以使用FileInputStream

2.2FileInputStream概述

构造方法

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

代码示例

示例一:文件的读取

将文件完全读取的两种方式。相比而言,后一种的IO次数更少,性能更好。

public class TestDemo7 {public static void main(String[] args) throws IOException {try(InputStream is = new FileInputStream("hello.txt")) {while (true) {int b = is.read();if (b == -1) {break;//表示文件结束}System.out.printf("%c", b);}}System.out.println();}
}
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;}for (int i = 0; i < len; i++) {System.out.printf("%c", buf[i]);}}}System.out.println();}

示例二:读取文件中的中文

注意:写文件的时候使用的是UTF-8编码后长度刚好为3个字节和长度不超过1024字节的现状,但是这种方式并不是通用的

public class TestDemo8 {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;}for (int i = 0; i < len; i += 3) {String s = new String(buf, i, 3, "UTF-8");System.out.printf("%s", s);}}System.out.println();}}
}

2.3利用Scanner进行字符读取

在上述的例子中,我们发现对字符类型直接使用InputStream进行读取是非常麻烦且困难

。所以我们使用熟悉的类来完成该工作,就是Scanner类。

构造方法 说明
Scanner(InputStream is, String charset) 使用charset字符集进行is的扫描

示例一使用Scanner来读取文件

import java.io.*;
import java.util.Scanner;/*** Describe:使用Scanner来读取文件* User:lenovo* Date:2023-04-11* Time:10:27*/
public class TestDemo9 {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);}}}System.out.println();}
}

 2.4OutputStream概述

方法

返回类型 方法签名 说明
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

2.5利用OutputStreamWriter进行字符写入

示例一使用write(int b)进行写入

public class TestDemo10 {public static void main(String[] args) throws IOException {try(OutputStream os = new FileOutputStream("output.txt")) {os.write('h');os.write('e');os.write('l');os.write('l');os.write('o');//一定要刷新缓冲区os.flush();}}
}

 【示例二】使用Write(byte[] b)进行写入

public static void main(String[] args) throws IOException{try(OutputStream os = new FileOutputStream("output.txt")) {byte[] b= new byte[] {'a', 'b', 'c', 'd', 'e'};os.write(b);os.flush();}}

 【示例三】使用write(byte b, int off, int len)进行写入

 public static void main(String[] args) throws IOException{try(OutputStream os = new FileOutputStream("output.txt")) {byte[] b = new byte[]{'*', 'n', 'i', ',', 'h', 'a', 'o'};os.write(b, 1, 6);os.flush();}}

2.6使用PrintWriter来写入

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

PrintWriter类中提供了我们熟悉的print/println/printf方法

public class TestDemo11 {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.println("hello world!");writer.flush();}}}}
}

 3.练习

3.1示例一

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


import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;/*** Describe:扫描指定目录,并找到名称中包含指定字符的所有文件(不包含目录),并且后序询问用户是否要删除该文件* User:lenovo* Date:2023-04-11* Time:13:53*/
public class TestDemo12 {public static void main(String[] args) throws IOException{Scanner scan = new Scanner(System.in);System.out.println("请输入要扫描的根目录(绝对途径或相对路径):");String rootDirPath = scan.next();File rootDir = new File(rootDirPath);if(!rootDir.isDirectory()) {System.out.println("您输入的根目录不存在或者不是目录,退出");return;}System.out.println("请输入要找出的文件名中的字符:");String token = scan.next();List<File> result = new ArrayList<>();//因为文件系统是树型结构,所以我们使用深度优先遍历(递归)完成scanDir(rootDir, token, result);System.out.println("共找到了符合条件的文件" + result.size() + "个,它们分别是");for(File file : result) {System.out.println(file.getCanonicalPath() + "是否删除文件?y/n");String in = scan.next();if(in.toLowerCase().equals("y")) {file.delete();}}}private static void scanDir(File rootDir, String token, List<File> result) {File[] files = rootDir.listFiles();if(files == null || files.length == 0) {return;}for(File file : files){if(file.isDirectory()) {scanDir(file, token, result);}else {if(file.getName().contains(token)) {result.add(file.getAbsoluteFile());}}}}
}

3.2示例二

进行普通文件的复制

import java.util.Scanner;
import java.io.*;
/*** Describe:普通文件的复制* User:lenovo* Date:2023-04-11* Time:14:12*/
public class TestDemo13 {public static void main(String[] args) throws IOException{Scanner scan = new Scanner(System.in);System.out.println("请输入要复制的文件(绝对路径或相对路径):");String sourcePath = scan.nextLine();File sourceFile =new File(sourcePath);if(!sourceFile.exists()) {System.out.println("文件不存在,退出");return;}if(!sourceFile.isFile()) {System.out.println("文件不是普通文件,退出");return;}System.out.println("请输入要复制到的目标路径(绝对路径或相对路径):");String destPath = scan.nextLine();File destFile = new File(destPath);if(destFile.exists()) {if(destFile.isDirectory()) {System.out.println("目标路径已经存在,并且是一个目录,退出");return;}}try(InputStream is = new FileInputStream(sourceFile)) {try(OutputStream os = new FileOutputStream(destFile)) {byte[] buf = new byte[1024];int len;while(true) {len = is.read(buf);if(len == -1) {break;}os.write(buf, 0, len);}os.flush();}}System.out.println("复制完成");}
}