文章目录

  • 1. 认识文件
  • 2. Java中操作文件
    • 2.1 File类
    • 2.2 文件内容的读写——数据流
      • InputStream类
      • 利用Scanner进行字符读取
      • OutputStream类
      • 利用PrintWriter写入
  • 3. 文件操作练习

1. 认识文件

针对硬盘这种持久化存储的I/O设备,当我们想要进行数据保存时,往往不是保存成一个整体,而是独立成一个个的单位进行保存,这个独立的单位就被抽象成文件的概念,类似于办公桌上的一份份真实的文件

文件除了有数据内容之外,还有一部分信息,例如文件名,文件类型,文件大小等并不作为文件的数据而存在,我们把这部分信息可以视为文件的元信息

文件的组织形式:按照层级结构进行组织,也就是树形结构,这样一种专门用来存放管理信息的特殊文件也就是我们平时所谓的文件夹或者目录

文件路径:从树形结构的角度来看,树中的每个节点都可以被从一条根开始,一直到达节点的路径所描述,这种描述方式就被称为文件的绝对路径,除了可以从根开始进行路径的描述,我们可以从任意节点出发,进行路径的描述,而这种描述方式就被称为相对路径,相当于当前所在节点的一条路径

2. Java中操作文件

2.1 File类

属性

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

构造方法

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

方法

修饰符及返回值类型 方法名 说明
String getParent() 返回File对象的父目录文件路径
String getName() 返回File对象的纯文件名你
String getPath() 返回File对象的文件路径
String getAbsolutePath() 返回File对象的绝对路径
String getCanonicalPath() 返回File对象的修饰过的绝对路径
boolean exists() 判断File对象描述的文件是否真实存在
boolean isDirectory() 判断File对象代表i的文件是否是一个目录
boolean isFile() 判断File对象代表的文件是否是一个普通文件
boolean createNewFile() 根据File对象,自动创建一个空文件,成功创建后,返回true
boolean delete() 根据File对象,删除该文件,成功删除后返回true
void deleteOnExit() 根据File对象,标注文件将被删除,删除动作会等到JVM运行结束后才进行
String[ ] list() 返回File对象代表的目录下的所有文件名
File[ ] listFiles() 返回File对象代表的目录下的所有文件,以File对象表示
boolean mkdir() 创建File对象代表的目录
boolean mkdirs() 创建File对象代表的目录,如果中间目录不存在,会创建中间目录
boolean renameTo(File dest) 进行文件改名,也可以视为剪切,粘贴操作
boolean canRead() 判断用户是否对文件有可读权限
boolean canWrite() 判断用户是否对文件有可写权限

示例1:

get系列方法的特点和差异

public class Main {public static void main(String[] args) throws IOException {File file = new File("./test.txt");//并不要求文件必须存在System.out.println(file.getParent());System.out.println(file.getName());System.out.println(file.getPath());System.out.println(file.getAbsolutePath());//返回 File 对象的绝对路径System.out.println(file.getCanonicalPath());//返回 File 对象的修饰过的绝对路径}
}
//执行结果
.
test.txt
.\test.txt
C:\Users\Freedom\IdeaProjects\test3\.\test.txt
C:\Users\Freedom\IdeaProjects\test3\Test.txt

示例2

普通文件的创建、删除

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());//文件不存在 falseSystem.out.println(file.isDirectory());//文件不存在,falseSystem.out.println(file.isFile());//文件不存在 falseSystem.out.println(file.createNewFile());//创建成功 trueSystem.out.println(file.exists());//文件存在 trueSystem.out.println(file.isDirectory());//文件不是目录 fasleSystem.out.println(file.isFile());//文件是普通文件 trueSystem.out.println(file.createNewFile());//文件已经存在,创建失败 false}
}
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"); // 要求该文件不存在,才能看到相同的现象System.out.println(file.exists());//文件不存在,falseSystem.out.println(file.createNewFile());//创建成功 trueSystem.out.println(file.exists());//文件存在 trueSystem.out.println(file.delete());//文件删除成功 trueSystem.out.println(file.exists());//文件不再存在,已被删除,false}
}

示例3

观察 deleteOnExit 的现象

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"); // 要求该文件不存在,才能看到相同的现象System.out.println(file.exists());//falseSystem.out.println(file.createNewFile());//trueSystem.out.println(file.exists());//truefile.deleteOnExit();//将文件标注为即将删除的文件System.out.println(file.exists());//true}
}//代码执行完毕后,才会删除文件,所以上面判断时,文件存在返回true

示例4:

目录的创建

import java.io.File;
import java.io.IOException;
public class Main {public static void main(String[] args) throws IOException {File dir = new File("some-dir"); // 要求该目录不存在,才能看到相同的现象System.out.println(dir.isDirectory());//目录不存在,falseSystem.out.println(dir.isFile());//文件不存在 falseSystem.out.println(dir.mkdir());//目录创建成功 trueSystem.out.println(dir.isDirectory());//文件是一个目录,trueSystem.out.println(dir.isFile());//不是普通文件 false}
}

示例5:

多级目录创建

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 和 some-dir 都不存在System.out.println(dir.isDirectory());//falseSystem.out.println(dir.isFile());//falseSystem.out.println(dir.mkdir());//false 只能创建一个目录System.out.println(dir.isDirectory());//falseSystem.out.println(dir.isFile());//false}
}
//mkdir() 的时候,如果中间目录不存在,则无法创建成功;
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 和 some-dir 都不存在System.out.println(dir.isDirectory());//false 文件不存在System.out.println(dir.isFile());//false 文件不存在System.out.println(dir.mkdirs());//true 创建多级目录成功System.out.println(dir.isDirectory());//true 文件是目录System.out.println(dir.isFile());//false  不是普通文件}
}

示例6:

文件重命名

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());//trueSystem.out.println(dest.exists());//falseSystem.out.println(file.renameTo(dest));//trueSystem.out.println(file.exists());//falseSystem.out.println(dest.exists());//true}
}

2.2 文件内容的读写——数据流

InputStream类

修饰符及返回值类型 方法名 说明
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的实现类有很多,基本可以认为不同的输入设备都可以对应要给InputStream类,从文件中读取使用FileInputStream

FileInputStream类

构造方法

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

示例1:

将文件完全读完的两种方式,第二种的IO次数更少,性能更好

public class Main {public static void main(String[] args) {try(InputStream inputStream = new FileInputStream("Test.txt")){//使用try()...catch执行完毕后,自动调用inputStream.close()关闭资源while(true){int b = inputStream.read();if(b == -1){break;}System.out.printf("%c",b);}} catch (IOException e) {e.printStackTrace();}}
}
public class Main {public static void main(String[] args) {//一次读取1024个字节try(InputStream inputStream = new FileInputStream("Test.txt")){byte [] buffer = new byte[1024];while(true){int len = inputStream.read(buffer);//返回值是buffer数组的长度if(len == -1){break;}for (int i = 0; i < len; i++) {//遍历这个buffer数组,打印每个元素System.out.printf("%c",buffer[i]);}}}catch (IOException e){e.printStackTrace();}}
}

示例2:

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

public class Test {public static void main(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("hello.txt")){byte [] buffer = new byte[1024];while(true){int len = inputStream.read(buffer);if(len == -1){break;}//这个操作只适用于纯中文的文件,如果文件中包含英文加汉字,就会出错for (int i = 0; i < len; i+=3) {String s = new String(buffer,i,3,"UTF-8");System.out.print(s);}}}catch (IOException e){e.printStackTrace();}}
}

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

利用Scanner进行字符读取

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

public class Test11 {public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("hello.txt")) {//scanner不仅可以从控制台读取,也可以从文件读取//sanner也有close方法,这个close方法也是用来关闭scanner中的inputStreamtry (Scanner scanner = new Scanner(inputStream, "UTF-8")) {while (scanner.hasNext()) {String s = scanner.next();System.out.println(s);}}} catch (IOException e) {e.printStackTrace();}}
}

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,用OutputStream的方式打开文件,会将文件原来的内容清空掉

利用OutputStreamWriter进行字符写入

示例:

import java.io.*;
public class Main {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');// 不要忘记 flushos.flush();}}
}
import java.io.*;
public class Main {public static void main(String[] args) throws IOException {try (OutputStream os = new FileOutputStream("output.txt")) {byte[] b = new byte[] {(byte)'G', (byte)'o', (byte)'o', (byte)'d'};os.write(b);//write(byte [] b)// 不要忘记 flushos.flush();}}
}
import java.io.*;
public class Main {public static void main(String[] args) throws IOException {try (OutputStream os = new FileOutputStream("output.txt")) {byte[] b = new byte[] {(byte)'G', (byte)'o', (byte)'o', (byte)'d', (byte)'B',
(byte)'a', (byte)'d'};os.write(b, 0, 4);//write(byte [] b,int off,int len)// 不要忘记 flushos.flush();}}
}
import java.io.*;
public class Main {public static void main(String[] args) throws IOException {try (OutputStream os = new FileOutputStream("output.txt")) {String s = "Nothing";byte[] b = s.getBytes();os.write(b);// 不要忘记 flushos.flush();}}
}
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);// 不要忘记 flushos.flush();}}
}

利用PrintWriter写入

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();}}}}
}

3. 文件操作练习

示例1:

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

public class Test {public static void main(String[] args) throws IOException {//1.让用户输入一个待扫描的根目录,和要查询的关键词System.out.println("请输入要扫描的根目录(绝对路径):");Scanner scanner = new Scanner(System.in);String root = scanner.next();File rootDir = new File(root);if(!rootDir.isDirectory()){System.out.println("输入的根目录有误");return;}System.out.println("输入要查找的文件名包含的关键词");String token = scanner.next();List<File> result = new ArrayList<>();//result表示递归遍历的结果,包含所有带有token关键词的文件//递归遍历目录scanDir(rootDir,token,result);//遍历result,根据用户的输入判断是否要删除该文件for (File file:result) {System.out.println(file.getCanonicalPath()+ " 是否要删除(Y/N)");String input = scanner.next();if(input.equals("Y")){file.delete();}}}//递归遍历目录,找出所有符合关键词的文件private static void scanDir(File rootDir, String token, List<File> result) throws IOException {//.list()返回的是文件名(String)  .listFiles()得到的是file对象,返回值是file类型的数组File [] files = rootDir.listFiles();if(files == null || files.length == 0){return;//说明当前的目录是一个空目录}//遍历files数组中的每个文件for (File file:files) {//如果当前文件是一个目录,就递归查找if (file.isDirectory()){scanDir(file,token,result);}else{//如果文件是一个普通文件,就判断文件名是否包含关键词if(file.getName().contains(token)){result.add(file.getCanonicalFile());}}}}
}

示例2:

进行普通文件的复制

public class Test15 {public static void main(String[] args) {System.out.println("请输入要复制的文件路径(绝对路径)");Scanner scanner = new Scanner(System.in);String srcPath = scanner.next();File srcFile = new File(srcPath);if(!srcFile.exists()){System.out.println("要复制的文件不存在");return;}System.out.println("请输入要复制到的目标路径(绝对路径)");String destPath = scanner.next();File destFile = new File(destPath);if (destFile.exists()){System.out.println("目标路径已存在");return;}//父目录不存在,就创建目录if(!destFile.getParentFile().exists()){destFile.mkdirs();}try(InputStream inputStream = new FileInputStream(srcFile);OutputStream outputStream = new FileOutputStream(destFile)){while (true){byte [] buffer = new byte[1024];int len = inputStream.read(buffer);if(len == -1){//len等于-1表示文件读取完毕break;}outputStream.write(buffer,0,len);}}catch(IOException e){e.printStackTrace();}System.out.println("复制完成");}
}

示例3:

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

public class Test16 {public static void main(String[] args) throws IOException {//1.用户输入要查询的根目录,判断是否为目录,如果不是,就退出程序System.out.println("输入要查询的根目录");Scanner scanner = new Scanner(System.in);String root = scanner.next();File rootDir = new File(root);if(!rootDir.isDirectory()){System.out.println("输入的目录有误");return;}//2.用户输入要查询的关键字System.out.println("输入要查询的关键字");String token = scanner.next();//result用来存储递归查找出的文件结果List<File> result = new ArrayList<>();//3.遍历目录,进行匹配判断scanDir(rootDir,token,result);//4。打印结果for (File f:result) {System.out.println(f.getCanonicalPath());}}private static void scanDir(File rootDir, String token, List<File> result) throws IOException {File [] files = rootDir.listFiles();//将rootDir中的所有内容以File类型的数组的形式组织//如果是一个空目录,直接返回if (files == null || files.length == 0){return;}//files不空,遍历这个目录for (File f:files) {if(f.isDirectory()){//如果是目录,就递归查询scanDir(f,token,result);}else{//是普通文件,判断文件名称中是否包含关键词if (f.getCanonicalPath().contains(token)){result.add(f);//判断文件内容是否包含关键词}else if(isContentContains(f,token)){result.add(f);}}}}private static boolean isContentContains(File f, String token) {StringBuilder stringBuilder = new StringBuilder();//打开f这个文件,依次取出每一行的结果,创建StringBuilder用来拼接每一行的内容,try(InputStream inputStream = new FileInputStream(f)){Scanner scanner = new Scanner(inputStream,"UTF-8");while(scanner.hasNextLine()){String line = scanner.nextLine();stringBuilder.append(line + "\n");//拼接line 并且换行}}catch (IOException e){e.printStackTrace();}//判断stringBuider中是否包含token,如果不等于-1说明包含,返回true。等于-1,说明不包含return stringBuilder.indexOf(token) != -1;//indexOf如果包含会返回具体的下标值,不包含就会返回-1}
}

代码参考

如何按字节进行数据读

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

如何按字节进行数据写

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

如何按字符进行数据读

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

如何按字符进行数据写

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

【文件操作(IO)】File类的属性,常见方法,文件内容的读写操作相关推荐

  1. 利用java.io.File类实现遍历本地磁盘上指定盘符或文件夹的所有的文件

    2016-11-18 这是本人的第一篇随笔博客,纠结了半天还是选择自己学的时候比较用心的一些知识点上.利用java.io.File类指定本地的文件夹进行遍历所有的文件. package org.lxm ...

  2. Java 文件操作(File类)

    在Java中,文件操作和流操作经常结合在一起进行,其中,文件操作主要是针对一个文件的增删改查和重命名,不涉及一个文件的内容的更改,关于具体文件内容的操作属于流操作的范畴.这里,先对文件操作进行的一些方 ...

  3. 33.JAVA编程思想——JAVA IO File类

    33.JAVA编程思想--JAVA IO File类 RandomAccessFile用于包括了已知长度记录的文件.以便我们能用 seek()从一条记录移至还有一条:然后读取或改动那些记录. 各记录的 ...

  4. java:IO流(缓冲流、对象流、控制台IO、转换流、java.io.File 类 )

    目录 一.IO 流的结构体系 二.缓冲流:BufferedInputStream & BufferedOutputStream 三.对象流:ObjectInputStream & Ob ...

  5. JavaSE-java.io.File类

    java.io.File类 1.java.io.File类 2.File类构造器-创建File类实例 3.File类常用方法 3.1.获取功能 3.2.重命名功能 3.3.File类的判断功能 3.4 ...

  6. 安卓上为什么不能用system.io.file读取streammingAssets目录下的文件

    安卓上为什么不能用system.io.file读取streammingAssets目录下的文件 首先,看文档: Streaming Assets Most assets in Unity are co ...

  7. C# File类读取.txt(简体/繁体字)文件进行简繁字体转换

    键值对集合中,有个例子是将简体字和繁体字作为键和值添加到键值对集合中,让用户输入文字,程序进行简繁字体转换 原参考思路是创建两个私有的常量分别储存简体字和繁体字,然后创建一个键值对集合,通过for循环 ...

  8. 基于MATLAB的面向对象编程(1)——类,属性,方法

    这里写目录标题 1 入门 1.1 如何把面条抽象成Class 1.2 文件类 2 基于MATLAB的面向对象编程入门 2.1 如何定义一个类(Class) 2.2 创建一个对象 2.3 类的属性 2. ...

  9. File类判断功能的方法

    package com.learn.demo01.File;import java.io.File;/*File类判断功能的方法- public boolean exists() :此File表示的文 ...

最新文章

  1. 限制系统扩展能力的瓶颈有哪些?
  2. Django组件-中间件
  3. java 数组下标6,这里为什么用equals会错,改==就不会?java入门第一集6.8获取数组下标课后练习...
  4. Matlab Tricks(十一)—— 向量的逆序输出
  5. VMware vSphere 5.1 vCenter安装
  6. C# Winform 实现屏蔽键盘的win和alt+F4的实现代码
  7. 深度学习图解 - 具备高中数学知识就能从入门到精通的神书 Andrew W· Trask
  8. 学生食堂信息管理系统
  9. 基于Matlab App Designer的语音信号分析与处理(一):语音信号的采集,时域、频域分析
  10. 【Python学习】Python的点滴积累
  11. 轻松实现支付宝服务窗网页授权从配置到获取授权获取用户信息
  12. iOS视频编辑SDK
  13. [暑假]简单认识一下常用的字体 <<微软雅黑 黑体 和 宋体>>
  14. SQL注入之Mssql注入及原理
  15. 边玩边学,13个 Python 小游戏真有趣啊(含源码)
  16. Involution 笔记:
  17. Hangzhou Invitation Day1
  18. 手机如何将Word文档转换为PDF扫描文件
  19. 如何批量生成文件夹并命名
  20. firefly-rk3288j开发板 TP实验之GT9XX触摸驱动

热门文章

  1. 【STM32学习】红外传感器实现——广告自动关闭和自动打开功能
  2. 老站调转新站最笨方法
  3. 用python画一个简单卡通人物_Python绘制可爱的卡通人物 | 【turtle使用】-Go语言中文社区...
  4. java wrapper作用_Java Service Wrapper 浅谈
  5. 驾考笔记:科目三满分攻略——荣县郝家坝科目三细节及线路详解
  6. Django admin登录页面验证码(1):普通字符和算术验证码
  7. 第一篇博客,至我生锈的大脑
  8. 霍尔效应电流传感器——以开环电流传感器实现闭环精度
  9. 仿QQ音乐播放界面(已实现主要功能)
  10. 怎样把扫描件转换成pdf工具