文件File
- File可以用来表示计算机中的文件或者文件夹
- 官方定义:文件和文件夹路径名的抽象表示形式
3种构造
- 1File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
- 2File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的File实例
- 3File(File parent, String child) 从父文件对象和子路径名字符串创建新的File实例
//1 写完整路径
File file1 = new File("H:\\aaa\\java.txt");
//2 父路径 加 子路径名字
File file2 = new File("H:\\aaa", "java.txt");
File aaa = new File("H:\\aaa"); //父路径生成一个File对象
//3 父路径的文件对象 加 子路径名字
File file3 = new File(aaa, "java.txt");
绝对路径和相对路径
- 绝对路径: 从盘符开始,一个文件的完整路径。
- 相对路径:
- 在idea中创建工程写java代码 ,相对路径指的是从工程的根目录开始的路径,
./
表示工程根目录,作为开头可以省略
- 在idea中创建工程写java代码 ,相对路径指的是从工程的根目录开始的路径,
File file = new File("aaa.txt");
file.createNewFile();//在工程目录project09下创建文件
File file1 = new File("mymodule\\src\\com\\heima\\test2\\bbb.txt");//在test2下创建文件
file1.createNewFile();
//这个是绝对路径 缺点是 工程如果拷贝到别的位置 就需要修改路径
File file11 = new File("C:\\Users\\halon\\Desktop\\java52\\day09\\project09\\mymodule\\src\\com\\heima\\test2\\bbb.txt");
// ../表示上一层目录 这里会在project09的上一层的上一层 也就是java52中创建a.txt
File file2 = new File("../../a.txt");
file2.createNewFile();
-
相对路径: 大众化的理解:相对于当前文件所在目录,
./
表示当前文件所在目录,作为开头可以省略 -
../
表示上一层目录 -
使用相对路径较多,方便代码的迁移
路径的分隔符
- 也可以使用File.separator 表示分隔符 System.out.println(“a” + File.separator + “b” + File.separator + “n”);
- 单斜杠作为分隔符更通用方便 / \
在windows中 \作为路径的分隔符,在java中用\\才能表示\
在java中也可以用/表示分隔符
代码
//相对路径
//File xiaohua1 = new File("module01\\src\\笑话大全.txt");//分割符\\
File xiaohua1 = new File("module01/src/笑话大全.txt");//分割符/
System.out.println(xiaohua1);
File创建方法
方法名 | 说明 |
---|---|
public boolean createNewFile() | 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 |
public boolean mkdir() | 创建由此抽象路径名命名的目录 |
public boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录 |
代码
- 三种创建返回值都是布尔
- 如果创建的文件或者目录已经存在,就不会重新创建了
- createNewFile如果创建的文件的目录不存在,报IOException异常
public static void main(String[] args) {
try {
//在mymodule下创建mm1文件 如果已经存在 不会重新创建
File file01 = new File("mymodule/mm1");
System.out.println(file01.createNewFile());
//mymodule01不存在 那么会报异常
File file02 = new File("mymodule01/mm1");
System.out.println(file02.createNewFile());
} catch (IOException e) {
e.printStackTrace();
}
}
//创建文件夹 mkdir 和 mkdirs
File file01 = new File("mymodule/a");
System.out.println(file01.mkdir());
File file02 = new File("mymodule/a/b");
System.out.println(file02.mkdir());
File file03 = new File("mymodule/m/n/x");
//mkdirs可以创建 多级目录 包括不存在的目录
System.out.println(file03.mkdirs());
//x1.txt创建出来也是目录, 和后缀名无关
File file04 = new File("mymodule/m/n/x1.txt");
System.out.println(file04.mkdirs());
注意:
- createNewFile 创建的是普通文件,和后缀名是什么无关
- mkdir和mkdirs 创建的是文件夹 和后缀名无关
删除
方法名 | 说明 |
---|---|
public boolean delete() | 删除由此抽象路径名表示的文件或目录 |
代码
- 删除后不会进入回收站
- 只能删除空文件夹
//删除后不会进入回收站
File file = new File("hehe..txt");
System.out.println(file.delete());
File file1 = new File("x/y/z.mp3");
System.out.println(file1.delete());
//只能删除空文件夹,需要先进入文件夹 删除里面的内容,然后再删除当前文件夹
File file2 = new File("x");
System.out.println(file2.delete());
判断
方法名 | 说明 |
---|---|
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
代码
File file = new File("module01\\src\\com\\heima\\test2", "Demo01.java");
System.out.println(file.isFile());
System.out.println(file.isDirectory());
System.out.println(file.exists());
File file2 = new File("module01\\src\\com\\heima\\test2");
System.out.println(file2.isFile());
System.out.println(file2.isDirectory());
System.out.println(file2.exists());
File file3 = new File("module01\\src\\com\\heima\\test3");
System.out.println(file3.isFile());
System.out.println(file3.isDirectory());
System.out.println(file3.exists());
获取
方法名 | 说明 |
---|---|
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
public File[] listFiles() | 获取当前目录里 的文件和文件夹的File对象放到一个数组里,返回数组 |
代码
File file02 = new File("mymodule/a/b");
System.out.println(file02.getAbsolutePath());//获取绝对路径 C:\Users\halon\Desktop\java52\day09\project09\mymodule\a\b
System.out.println(file02.getPath());//获取创建文件对象的时候传入的路径 mymodule/a/b
System.out.println(file02.getName());//获取文件名字 b
File file03 = new File("mymodule/m/n");
//获取当前目录里 的文件和文件夹的File对象放到一个数组里
File[] files = file03.listFiles();
for (File file : files) {
System.out.println(file.getName());
}
File类练习一【应用】
-
案例需求
在当前模块下的aaa文件夹中创建一个a.txt文件
-
实现步骤
- 创建File对象,指向aaa文件夹
- 判断aaa文件夹是否存在,如果不存在则创建
- 创建File对象,指向aaa文件夹下的a.txt文件
- 创建这个文件
代码
- 注意aaa不存在,直接创建a.txt会报错
//创建文件对象 路径是aaa文件夹
File dir01 = new File("mymodule/aaa");
//判断dir01是否存在 如果不存在 把目录创建出来
if (!dir01.exists()) {
System.out.println("不存在 创建aaa");
dir01.mkdirs();
}
//在aaa下面创建a.txt
File f = new File(dir01, "a.txt");
f.createNewFile();
递归删除一个文件夹
package com.heima.test4;
import java.io.File;
public class Demo01 {
public static void main(String[] args) {
File aFile = new File("mymodule/aaa2");
delFile(aFile);
}
/**
* 删除文件夹
* dir 被删除的文件夹的对象
*/
public static void delFile(File dir) {
System.out.println("进入了" + dir.getName());
//1 获取dir里面所有的文件对象
File[] files = dir.listFiles();
//2遍历files
for (File file : files) {
//System.out.println(file.getName());
//判断file是不是文件
if (file.isFile()) {
System.out.println("开始删除" + file.getName());
//如果是文件 直接删除
file.delete();
} else {
//如果是文件夹 递归继续删除
delFile(file);
}
}
//循环清空文件夹后 把当前的文件夹删除
System.out.println("把" + dir.getName() + "删除");
dir.delete();
}
}
原理图
递归遍历文件夹,计算文件夹中所有文件的大小
public static void main(String[] args) {
//File file1 = new File("a.txt");
//System.out.println(file1.length());
File file = new File("mymodule/xx1");
System.out.println(getSize(file));
}
/**
* 获取file的大小
* @param file 文件夹对象
*/
public static long getSize(File file) {
long size = 0;
//1 获取所有文件对象
File[] files = file.listFiles();
//2 遍历
for (File f : files) {
//3判断是否是文件
if (f.isFile()) {
//3.1如果是文件 计算大小 累加起来
size += f.length();
} else {
//3.2如果是文件夹 让getSize去计算大小 然后也要累加起来
size += getSize(f);
}
}
//4返回file文件夹的大小
return size;
}
统计一个文件夹中每种类型文件的个数并打印(多练习几次)
以后缀名作为判断依据
mp3文件 1个
avi文件 3个
txt文件 7个
jpeg文件 5个
png文件 3个
mp4
mp4
mp3
mp3
png
jpg
png
png
txt
png
txt
java
用后缀做为key 数量作为值
HashMap<String,Integer> map = new HashMap<>();
存之前先获取数据
Integer vv = map.get("mp4");
if (vv == null) {
//说明之前没有存过mp4
map.put("mp4", 1);
} else {
map.put("mp4", vv + 1);
}
- 1 遍历文件夹里的所有的文件对象,获取每个文件的后缀名
- 2 把后缀名存入map, 后缀名作为key 出现的次数作为value
- 3 先去map里根据后缀名 获取值
- 4 如果获取到数据 说明之前已经存储过次数,再次存入的数量要+1
- 5 如果没有获取到数据 说明之前没有存储过
代码
package com.heima.test5;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
public class Demo02 {
public static void main(String[] args) {
File aFile = new File("mymodule/aaa");
//用后缀做为key 数量作为值 创建map对象
HashMap<String, Integer> map = new HashMap<>();
//计算aaa文件夹中每种类型的文件的数量 存储到map中
getTypeCount(map, aFile);
System.out.println(map);
}
//计算dir文件夹中每种类型的文件的数量
public static void getTypeCount(HashMap<String, Integer> map, File dir) {
//1获取所有文件对象
File[] files = dir.listFiles();
//2遍历所有文件对象
for (File file : files) {
//3判断file是不是文件
if (file.isFile()) {
//如果是文件 .png .txt .java .mp4 .mp3 需要获取类型
String filename = file.getName();
//按点来切割 注意 要有两个反斜杠
String[] ss = filename.split("\\.");
//获取后缀
String houzhui = ss[ss.length - 1];
//System.out.println(houzhui);
//先根据后缀去map里获取它的数量
Integer count = map.get(houzhui);
if (count == null) {
//如果count是null 说明之前没有存储过这个后缀 这里是第一次遇到
map.put(houzhui, 1);
} else {
//如果count不是null 那么就是之前的数量 把数量+1再次存储
map.put(houzhui, count + 1);
}
} else {
//如果是文件夹 就递归调用
getTypeCount(map, file);
}
}
}
}
小结
File类构造方法
public File(String pathname) :通过路径名创建新的 File对象。
public File(String parent, String child) :通过父路径和子路径创建File对象
public File(File parent, String child) :通过父路径和子路径创建File对象
File类成员方法
public String getName() :获取构造方法中路径的名称(末尾部分)
public String getAbsolutePath() : 获取构造方法中路径的绝对路径
public String getPath() : 获取创建对象时传入的路径
public long length() :获取文件的大小,单位是字节
public boolean isDirectory() :是否为目录(文件夹)。
public boolean exists() :判断构造方法中传递的路径是否存在
public boolean createNewFile() :文件不存在,创建一个新的空文件。
public boolean mkdir() :创建单级文件夹
public boolean mkdirs() :即可以创建单级文件夹,又可以创建多级文件夹
public boolean delete() :删除文件和文件夹,不走回收站
public String[] list() :遍历文件夹,返回一个String数组
public File[] listFiles() :遍历文件夹,返回一个File数组
IO流
介绍
- IO:输入/输出(Input/Output)
- 流:指数据,也可以叫数据流
- IO流就是用来处理设备间数据传输问题的.常见的应用: 文件复制; 文件上传; 文件下载,音视频播放
IO流的分类
-
按照数据的流向
- 输入流:读数据, 把数据从其他设备上读取到内存中的流。
- 输出流:写数据, 把数据从内存中写出到其他设备上的流。
-
按照数据类型来分
- 字节流 :以字节为单位,读写数据的流。
- 字节输入流
- 字节输出流
- 字符流 :以字符为单位,读写数据的流
- 字符输入流
- 字符输出流
- 字节流 :以字节为单位,读写数据的流。
IO流的使用场景注意:
- 如果操作的是纯文本文件,优先使用字符流, 能用记事本打开看的懂的就是纯文本文件。
- 如果操作的是图片、视频、音频等二进制文件,优先使用字节流
- 如果不确定文件类型,优先使用字节流.字节流是万能的流
字节流输出流(写数据到硬盘)
- OutputStream: 抽象类,表示字节输出流的所有类的超类
实用子类: FileOutputStream类
- 构造:
- public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。
- public FileOutputStream(String name): 创建文件输出流以指定的路径写入文件。
- 当你创建一个流对象时,必须传入一个文件或者文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,创建一个新的空白文件覆盖已有的文件。
使用的三步
- 1创建字节输出流对象
- 2调用字节输出流对象的写数据方法
- 3释放资源
代码
//1创建FileOutputStream对象
//如果文件不存在 会被创建
//如果文件存在 会被新的文件覆盖
FileOutputStream fos = new FileOutputStream("module01/aaa/b.txt");
//2写内容
// 输入的数字 会被转为码表中的字母
fos.write(99);//c
fos.write(70);//F
fos.write(50);//2
//3关闭流 把文件资源释放
fos.close();
注意:
- 1.如果文件不存在,会帮我们创建 如果文件存在,会清空之前的内容
- 2.输出的整数,实际是码表中的字母
- 3 每次使用完流 一定要关闭流,释放资源
一次写多个数据
- 写数据的方法分类
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流 一次写一个字节数据 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据 |
代码
//1构造 接收一个文件路径 或者一个文件对象
FileOutputStream fos = new FileOutputStream("ddd.txt");
//2 写内容
fos.write(100);
fos.write(101);
fos.write(102);
fos.write(103);
fos.write(104);
//可以直接写入一个byte数组
fos.write(new byte[]{66, 67, 68, 69, 70});
//把字符串转为byte数组 输出到文件
fos.write("你好".getBytes());
//void write(byte[] b, int off, int len)
byte[] bs = {71, 72, 73, 74, 75};
//把bs数组 偏移一个 然后写到文件里3个字节 这里是72 73 74写到文件里了
fos.write(bs, 1, 3);
//3 关闭流 释放文件
fos.close();
注意
- 如果要写入字符串,就把字符串通过getBytes()方法转为byte数组
写入汉字
- 用汉字的字符串转字节数组
fos.write("你好吗哈哈哈".getBytes());
字节流写数据如何实现换行
- windows:\r\n
- linux:\n
- mac:\r
字节流写数据如何实现追加写入
- public FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
代码
//第二个参数为true 表示从后面追加写入数据
FileOutputStream fos = new FileOutputStream("module01/aaa/c.txt",true);
for (int i = 0; i < 5; i++) {
fos.write("你好吗哈哈哈".getBytes());
//回车 换行
fos.write("\r\n".getBytes());
}
//3关闭流 把文件资源释放
fos.close();
异常处理
格式
- try-catch-finally
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
- finally特点
- 被finally控制的语句一定会执行,除非JVM退出
加入finally来实现释放资源
代码
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//System.out.println(2/0);
fos = new FileOutputStream("D:\\a.txt");
fos.write(97);
} catch (IOException e) {
e.printStackTrace();
} finally {
//finally语句里面的代码,一定会被执行.
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
try-with-resources的方式释放资源(掌握)
- 把需要释放资源对象的创建 放到try后面的小括号里 会自动在用完后被释放
public static void main(String[] args) {
//try-with-resources的方式释放资源
//把需要释放资源对象的创建 放到try后面的小括号里 会自动在用完后被释放
try (
//参1接收一个文件路径 或者一个文件对象
// 参2 设置为true表示追加写入内容
FileOutputStream fos = new FileOutputStream("a.txt", true);
FileOutputStream fos1 = new FileOutputStream("b.txt", true);
) {
//2 写内容
fos.write("nihao".getBytes());
fos1.write("nihao".getBytes());
} catch (IOException e) {
e.printStackTrace();
} catch (ArithmeticException e) {
System.out.println("除数为0");
}
}
字节流读数据 inputstream
字节输入流FileInputStream 构造方法
- FileInputStream(File file): 创建一个 FileInputStream ,该文件由文件系统中的文件对象 file命名。
- FileInputStream(String name): 创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
- 当你创建一个流对象时,必须传入一个文件或者文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException
其它方法
- public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
- public abstract int read(): 从输入流读取数据的下一个字节。
- public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 ,返回读取的长度,如果没有数据,返回-1。
读取一个字节的代码
public static void main(String[] args) throws IOException {
//1创建对象
FileInputStream fis = new FileInputStream("module01/bbb/a.txt");
//2读取数据 一次读取一个字节
int read = fis.read();
System.out.println(read);
//3关闭流
fis.close();
}
读取多个字节到数组的代码
public static void main(String[] args) throws IOException {
//1创建对象
FileInputStream fis = new FileInputStream("module01/bbb/a.txt");
byte[] bs = new byte[10];
//2读取数据到数组中,读取后会把字母转回编码的整数 返回读取的长度
//这里数组长度为10 一次就读取了10个字节
int result = fis.read(bs);
System.out.println(result);//10
System.out.println(Arrays.toString(bs));//[99, 115, 97, 100, 102, 115, 97, 100, 106, 108]
//3关闭流
fis.close();
}
注意:
- 1创建 FileInputStream对象时 文件不存在 报错
- 2读取的是编码数字,需要转为char
循环读取一个文件的内容(重点)
- public String(byte bytes[], int offset, int length)
- 参1 表示要被转换的字节数组
- 参2表示从头偏移多少个
- 参3表示 取几个数据转为字符串
- fis.read(bt) 读取内容到数组,如果读到数据,返回读取的长度,如果数据没有了,会返回-1
//1获取FileInputStream对象
try (FileInputStream fis = new FileInputStream("a.txt")) {
byte[] bytes = new byte[10];
int len;
//读取内容到数组,如果读到数据,返回读取的长度,如果数据没有了,会返回-1
//循环读取文件 当len为-1时停止循环
while ((len = fis.read(bytes)) != -1) {
//每次读取的内容转为字符串
//newString里的参1 表示要被转换的字节数组 参2表示从头偏移多少个,参3表示 取几个数据转为字符串
System.out.println(new String(bt, 0, len));
}
//fis.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
读取中文
- 一个中文占3个字节
文件复制练习
一次读一个字节
- 注意循环条件里的括号 容易写错
//复制一个文件
// 用输入流 读取文件b的内容 然后用输出流把读取的内容 写入到一个新的文件
public static void main(String[] args) throws IOException {
//1创建输入流对象 读取
FileInputStream fis = new FileInputStream("module01/aaa/b.txt");
//2创建输出流对象 写入
FileOutputStream fos = new FileOutputStream("module01/aaa/b附件.txt");
int by;
//一个字节一个字节的循环读取,如果读取到-1说明读完了 结束循环
while ((by = fis.read()) != -1) {
System.out.println(by);
//把读取的字节by写入到新的文件
fos.write(by);
}
//3关闭流
fis.close();
fos.close();
}
一次读多个字节(做到自己独立完成)
- 注意写入数据时,写入的是len的长度,fos.write(bt, 0, len);
public static void main(String[] args) {
File file1 = new File("mymodule/无间道.mp3");
File file2 = new File("mymodule/无间道备份.mp3");
copy(file1, file2);
}
/**
* 把file1拷贝到file2
*
* @param file1
* @param file2
*/
public static void copy(File file1, File file2) {
try (
//创建文件的读取流
FileInputStream fis = new FileInputStream(file1);
//创建文件的写入流
FileOutputStream fos = new FileOutputStream(file2);
) {
//创建一个byte数组
byte[] bts = new byte[1024];
//定义一个变量len表示读取的长度
int len = 0;
//循环读取数据到数组bts中
while ((len = fis.read(bts)) != -1) {
//把每次读取的内容 写入到新的文件
fos.write(bts, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
内容总结
File
创建文件 和文件夹
删除文件 和文件夹(递归删除)
获取文件夹里所有文件
获取文件大小
获取文件路径
io
FileOutputStream 写 一次可以写一个字节 也可以写多个字节
FileInputStream 读 一次可以读一个字节 也可以读多个字节
复制文件