一 File类
1.File类的介绍
java.io.File类
文件和目录路径名的抽象表示形式。
File类封装了计算机中的文件和文件夹,可以通过File类中的方法来操作计算机中的文件和文件夹(目录)
包括创建、删除、获取、法遍历文件夹以及法获取文件的大小(字节)
必须记住3个英文单词
file:文件
directory:文件夹,目录
path:路径
2.File类的静态成员变量
File类是一个与系统无关的类,任何的操作系统都可以使用File类中的方法和变量
File类中的静态的成员变量
- static String pathSeparator 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
- static char pathSeparatorChar 与系统有关的路径分隔符。
- static String separator 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
- static char separatorChar 与系统有关的默认名称分隔符。
package com.shiyitiancheng.demo01;
import java.io.File;
public class Demo {
public static void main(String[] args) {
String pathSeparator = File.pathSeparator;
System.out.println(pathSeparator);//路径分隔符 windows系统:分号(;) linux系统:冒号(:)
String separator = File.separator;
System.out.println(separator);//默认名称(文件夹名称)分隔符 windows系统:反斜杠(\) linux系统:正斜杠(/)
//工作中
String path = "d:\\a.txt";
System.out.println(path);
String path2 = "d:"+File.separator+"a.txt";
System.out.println(path2);
}
}
/*
;
\
d:\a.txt
d:\a.txt
*/
3.路径
路径:操作计算机中文件和文件的路径
分类:
1.绝对路径:以盘符(c:,D:,e:)开始的路径(唯一)
c:\a.txt
D:\a\aa\aaa
D:\study\myProject\day15
2.相对路径:相对于我们当前项目的根目录而言,我们使用项目的根目录作为路径,可以省略书写
绝对路径: D:\study\myProject\day15
相对路径:可以省略项目的根目录,java会自动给我们在路径的前边添加项目的根目录
D:\study\myProject\day15==>day15(相对)
D:\study\myProject\a.txt==>a.txt(相对)
aa\bb\cc\b.txt(相对)==>D:\study\myProject\day15\aa\bb\cc\b.txt(绝对)
注意:
- 路径是不区分大小写的 d:\a.txt D:\A.TXT
- 如果要使用反斜杠()作为文件|文件夹的分隔符,需要写两个(\),一个反斜杠本身是转义字符,有特殊含义
- 在java程序中,也可以使用一个正斜杠(/)作为文件|文件夹的分割符号
4.File的构造方法
import java.io.File;
/*
File类的构造方法
如果类中的方法不是静态的
只能使用构造方法创建对象,才能调用类中的方法
*/
public class Demo02File {
public static void main(String[] args) {
show02("c:\\","a.txt");//c:\a.txt
show02("d:\\","a.txt");//d:\a.txt
show02("d:\\","aaa\\bb\\cc\\dd");//d:\aaa\bb\cc\dd
show03();
}
/*
File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
参数:把构造方法参数的路径分割为了两部分
File parent:父路径
String child:子路径
好处:
1.父路径和子路径分别使用不同的路径,组装为一个新的路径,使用起来更加灵活
2.父路径类型是File,可以使用File的方法对父路径进行一些操作,在和子路径组成一个新的File对象
*/
private static void show03() {
File parent = new File("d:\\");
File file = new File(parent,"a.txt");
System.out.println(file);//d:\a.txt
}
/*
File(String parent, String child) 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
参数:把构造方法参数的路径分割为了两部分
String parent:父路径
String child:子路径
好处:
父路径和子路径分别使用不同的路径,组装为一个新的路径,使用起来更加灵活
*/
private static void show02(String parent, String child) {
File file = new File(parent,child);
System.out.println(file);
}
/*
File(String pathname) 创建一个新 File 实例。
参数:
String pathname:文件|文件夹路径名称
注意:
1.参数传递路径可以是绝对路径,也可以是相对路径
2.参数传递路径可以是以文件结尾的路径,也可以使用以文件夹结尾的路径
3.参数传递路径可以是真实存在的,也可以是不存在;构造方法仅仅是把字符串的路径,
封装为File对象,不检查路径的真实情况
*/
private static void show01() {
File f1 = new File("c:\\a.txt");
System.out.println(f1);//调用对象的toString方法 c:\a.txt
//File f2 = new File("d:\\aaa\\bbb\\ccc\\ddd");
File f2 = new File("d:/aaa/bbb/ccc/ddd");
System.out.println(f2);//d:\aaa\bbb\ccc\ddd
File f3 = new File("day15");
System.out.println(f3);//(D:\Work_idea\EE1234\day15)day15
}
}
5.File类的成员方法_获取功能的方法
import java.io.File;
/*
File类的成员方法_获取功能的方法(重点)
public String getAbsolutePath() :返回此File的绝对路径名字符串。
public String getPath() :将此File转换为路径名字符串。
public String getName() :返回由此File表示的文件或目录的名称。
public long length() :返回由此File表示的文件的长度。 不能获取目录的长度。
*/
public class Demo03FileMethod {
public static void main(String[] args) {
show04();
}
/*
public long length() :返回由此File表示的文件的长度。 不能获取目录的长度。
获取文件的大小,单位是字节
注意:
1.length方法只能获取文件的大小,不能获取文件夹的大小
2.length方法获取的构造方法传递文件路径的大小
3.如果传递文件路径不存在,那么此方法返回0
*/
private static void show04() {
File f1 = new File( "f:\\a.txt");
System.out.println(f1.length());54
File f2 = new File("f:\\test");
System.out.println(f2.length());//0文件夹不能获取大小的
}
/*
public String getName() :获取构造方法中路径末尾部分的文件|文件夹的名称
*/
private static void show03() {
File f1 = new File("c:\\aaa\\bbb\\ccc\\a.txt");
System.out.println(f1.getName());//a.txt
File f2 = new File("c:\\aaa\\bbb\\ccc");
System.out.println(f2.getName());//ccc
File f3 = new File("day15\\abc\\b.jpg");
System.out.println(f3.getName());//b.jpg
}
/*
public String getPath() :将此File转换为路径名字符串。
获取构造方法中传递的路径;传递路径是绝对的就返回绝对的;传递的路径是相对的,就返回相对路径
File类重写了Object类的toString方法
toString方法的底层源码:
public String toString() {
return getPath();
}
*/
private static void show02() {
File f1 = new File( "f:\\a.txt");
String path = f1.getPath();
System.out.println(path);//f:\a.txt
File f2 = new File("day15");
System.out.println(f2.getPath());//day15
System.out.println(f2.toString());//day15
System.out.println(f2);//day15
}
/*
public String getAbsolutePath() :返回此File的绝对路径名字符串。
获取构造方法中传递的路径;传递路径是绝对的,就返回绝对路径;传递的路径是相对的,会在相对路径前添加上项目根目录
*/
private static void show01() {
File f1 = new File("f:\\a.txt");
String a1 = f1.getAbsolutePath();// f:\a.txt
System.out.println(a1);
File f2 = new File("day15");
System.out.println(f2.getAbsoluteFile());//D:\myProject\xtqstudy\day15
}
}
6.文件的大小和文件的占用空间
计算机的硬盘默认是以4KB(4个字节)作为一个最小单位进行分割的,把计算机硬盘分割成无数多个小格子每个格子的大小就是4096个字节,如果往硬盘中存入数据,数据 没有4096大小,也占用4kb大小
7.File类的成员方法_判断功能的方法
import java.io.File;
/*
File类的成员方法_判断功能的方法(重点)
public boolean exists() :此File表示的文件或目录是否实际存在。
public boolean isDirectory() :此File表示的是否为目录。
public boolean isFile() :此File表示的是否为文件。
*/
public class Demo04FileMethod {
public static void main(String[] args) {
show02();
}
/*
public boolean isDirectory() :判断构造方法中传递的路径是否是以文件夹结尾的路径
是文件夹结尾:返回true
不是文件夹结尾:返回false
public boolean isFile() :判断构造方法中传递的路径是否是以文件结尾的路径
是文件结尾:返回true
不是文件结尾:返回false
注意:
1.构造方法中路径必须是存在的,才能判断路径是文件夹结尾还是文件结尾;否则没有意义,都会返回false
2.计算机中只有文件和文件夹,所以两个方法互斥
*/
private static void show02() {
//File f1 = new File("c:\\abc.txt");
File f1 = new File("c:\\a.txt");
//判断是否是文件还是文件夹之前,先判断路径是否存在
if(f1.exists()){
System.out.println(f1.isDirectory());//false
System.out.println(f1.isFile());//true
}
System.out.println("------------------------");
File f2 = new File("day15");
if(f2.exists()){
System.out.println(f2.isDirectory());//true
System.out.println(f2.isFile());//false
}
}
/*
public boolean exists() :判断构造方法中的路径是否存在
存在:返回true
不存在:返回false
*/
private static void show01() {
File f1 = new File("c:\\a.txt");
System.out.println(f1.exists());//true
File f2 = new File("c:\\abc.txt");
System.out.println(f2.exists());//false
File f3 = new File("day15");//day15==>相当于D:\Work_idea\EE1234\day15
System.out.println(f3.exists());//true
File f4 = new File("day16");
System.out.println(f4.exists());//false
}
}
8.File类的成员方法_创建删除功能的方法
import java.io.File;
import java.io.IOException;
/*
File类的成员方法_创建删除功能的方法(重点)
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean mkdir() :创建由此File表示的目录。
public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录
public boolean delete() :删除由此File表示的文件或目录。
*/
public class Demo05FileMethod {
public static void main(String[] args) throws IOException {
show03();
}
/*
public boolean delete() 删除构造方法中指定的文件|文件夹
返回值:boolean
构造方法中路径存在,删除文件|文件夹,返回true
构造方法中路径不存在或者文件夹中有内容,不会删除,返回false
注意:
此删除方法不走回收站,直接在硬盘上删除,需要谨慎
*/
private static void show03() {
File f1 = new File("day15\\a");
System.out.println(f1.delete());
File f2 = new File("day15\\b.txt");
System.out.println(f2.delete());
File f3 = new File("day15\\aaa");
System.out.println(f3.delete());//false 文件夹有内容,不会删除
}
/*
public boolean mkdir() :只能创建单级文件夹
public boolean mkdirs() :既能创建单级文件夹,又能创建多级文件夹
返回值:boolean
文件夹不存在,创建成功,返回true
文件夹存在,不会创建返回false;构造方法中传递的路径不存在,返回false
注意:
1.创建文件夹的名称和路径在构造方法中给出
2.此方法只能创建文件夹,不能创建
*/
private static void show02() {
File f1 = new File("day15\\a");//单级文件夹
System.out.println(f1.mkdir());
File f2 = new File("day15\\aaa\\bbb\\ccc\\ddd\\eee");//多级文件夹
System.out.println(f2.mkdirs());
File f3 = new File("w:\\a");
System.out.println(f3.mkdir());//false 路径不存在
File f4 = new File("day15\\c.txt");
System.out.println(f4.mkdir());//会不会报错? 不会 创建的是什么:是文件夹,名称叫c.txt
}
/*
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
作用:用于创建一个新的空白文件
返回值:boolean
true:文件不存在,创建成功,返回true
false:文件存在,不会创建新的,返回false(不会覆盖)
注意:
1.此方法只能创建文件,不能创建文件夹
2.创建文件的名称和路径在构造方法中给出
3.构造方法中写的文件的路径必须是存在的,否则会抛出异常
4.有些操作系统,c盘是否没有权限创建文件的,会抛出拒绝访问异常
*/
private static void show01() throws IOException {
File f1 = new File("d:\\a.txt");
boolean b1 = f1.createNewFile();
System.out.println("b1:"+b1);
File f2 = new File("day15\\b.txt");
System.out.println(f2.createNewFile());
File f3 = new File("e:\\c.txt");
//System.out.println(f3.createNewFile());//java.io.IOException: 系统找不到指定的路径。
File f4 = new File("d:\\aaaa\\c.txt");
//System.out.println(f4.createNewFile());//IOException: 系统找不到指定的路径。
File f5 = new File("day15\\新建文件夹");
System.out.println(f5.createNewFile());//创建的是什么?创建的就是一个文件夹,没有后缀名,文件的名称叫"新建文件夹"
}
}
9.File类的成员方法_目录遍历的方法
import java.io.File;
/*
File类的成员方法_目录遍历的方法(重点)
public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。
遍历目录(文件夹),获取目录中每一个文件|文件夹的名称,把多个名称存储到一个String类型的数组中返回
public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。
遍历目录(文件夹),获取目录中每一个文件|文件夹,把文件|文件夹封装为File对象,多个File对象存储到一个File类型的数组中返回
注意:
1.遍历目录的路径,在构造方法中给出
2.遍历的目录必须是存在的,否则会抛出空指针异常
3.这个方法只能遍历目录,不能遍历文件,否则会抛出空指针异常
*/
public class Demo06FileMethod {
public static void main(String[] args) {
show02();
}
/*
public File[] listFiles() :
遍历目录(文件夹),获取目录中每一个文件|文件夹,把文件|文件夹封装为File对象,多个File对象存储到一个File类型的数组中返回
*/
private static void show02() {
//File file = new File("c:\\a.txt");//NullPointerException 不能遍历文件
//File file = new File("w:\\abc");//NullPointerException 路径不存在
File file = new File("D:\\test\\test2\\test3");
File[] files = file.listFiles();
for (File f : files) {
//System.out.println(f.toString());
System.out.println(f.getName());
}
}
/*
public String[] list()
遍历目录(文件夹),获取目录中每一个文件|文件夹的名称,把多个名称存储到一个String类型的数组中返回
*/
private static void show01() {
File file = new File("D:\\test\\test2\\test3");
String[] arr = file.list();
for (String fileName : arr) {
System.out.println(fileName);
}
}
}
二.递归
/*
递归:方法自己调用自己
递归分类:
1.直接递归
public void a(){
a();
}
2.间接递归
public void a(){
b();
}
public void b(){
a();
}
递归的注意事项:
1.递归必须有结束的条件,保证递归可以停下来,否则会抛出内存溢出的错误
2.递归有结束的条件,但是递归次数也不能太多,否则会抛出内存溢出的错误
3.构造方法禁止递归
什么时候使用递归:
当我们频繁的调用某一个方法,方法的主体不变,每次调用方法的参数改变,就可以使用递归
*/
public class Demo01Recursion {
public static void main(String[] args) {
//a();
b(1);
}
/*
3.构造方法禁止递归
构造方法是创建对象使用的,递归调用自己,会在内存中一直创建无数多个对象
*/
public Demo01Recursion() {
//Demo01Recursion();
}
/*
2.递归有结束的条件,但是递归次数也不能太多,否则会抛出内存溢出的错误
10845,11063 内存的使用率随时在变化,得到的结果不一样
Exception in thread "main" java.lang.StackOverflowError
*/
private static void b(int i) {//1,2,3,4,5...
System.out.println(i);
if(i==20000){
return;//结束方法,不在继续调用
}
b(++i);
}
/*
1.递归必须有结束的条件,保证递归可以停下来,否则会抛出内存溢出的错误
Exception in thread "main" java.lang.StackOverflowError
*/
private static void a() {
System.out.println("a方法!");
a();
}
}
使用递归遍历文件夹和文件夹中的子文件夹
import java.io.File;
/*
练习:使用递归遍历文件夹和文件夹中的子文件夹(遍历多级文件夹)
遍历d:\\aaa目录
d:\\aaa
d:\\aaa\\aaa.java
d:\\aaa\\aaa.txt
d:\\aaa\\a
d:\\aaa\\a\\a.java
d:\\aaa\\a\\a.jpg
d:\\aaa\\b
d:\\aaa\\b\\B.JAVA
d:\\aaa\\b\\b.avi
*/
public class Demo04Recursion {
public static void main(String[] args) {
File file = new File("d:\\aaa");
getAllFile(file);
}
/*
定义一个方法,参数传递要遍历的文件夹的File对象
在方法内部对文件夹进行遍历
*/
public static void getAllFile(File dir){
System.out.println(dir);//打印要遍历的文件夹的名称
File[] files = dir.listFiles();
for (File f : files) {
//判断遍历得到的f,是否是一个文件夹
if(f.isDirectory()){
//f是一个文件夹,继续遍历这个文件夹
//我们发现getAllFile方法,就是一个传递文件夹,遍历文件夹的方法
//调用getAllFile方法,传递要遍历的文件夹即可(f==a,f==b)
getAllFile(f);//方法自己调用自己==>递归
}else{
//f就是一个文件,打印==>f.toString()方法
System.out.println(f);
}
}
}
}
文件搜索
import java.io.File;
/*
使用递归遍历文件夹和文件夹中的子文件夹(遍历多级文件夹)
遍历d:\\aaa目录,只打印以.java结尾的文件,不区分大小写
d:\\aaa
d:\\aaa\\aaa.java
d:\\aaa\\aaa.txt
d:\\aaa\\a
d:\\aaa\\a\\a.java
d:\\aaa\\a\\a.jpg
d:\\aaa\\b
d:\\aaa\\b\\B.JAVA
d:\\aaa\\b\\b.avi
*/
public class Demo05Recursion {
public static void main(String[] args) {
File file = new File("d:\\");
getAllFile(file);
}
/*
定义一个方法,参数传递要遍历的文件夹的File对象
在方法内部对文件夹进行遍历
*/
public static void getAllFile(File dir){
File[] files = dir.listFiles();
//在工作中,会对要遍历的数组|集合进行一个非空的判断,不是空在遍历,防止空指针异常
if(files!=null && files.length!=0){
for (File f : files) {
//判断遍历得到的f,是否是一个文件夹
if(f.isDirectory()){
getAllFile(f);//方法自己调用自己==>递归
}else{
/*
f就是一个文件,打印==>f.toString()方法
需求:只打印以.java结尾的文件,不区分大小写
解决:
判断f是否是一个以.java结尾的文件,是则打印
实现步骤:
1.把f对象(File对象)转换为String
a==>f.toString() "d:\\aaa\\aaa.java"
b==>f.getPath() "d:\\aaa\\aaa.java"
c==>f.getName() "aaa.java"
2.使用String类中的方法endsWith判断字符串是否是以.java结尾
3.是.java结尾的文件则打印
*/
//String name = f.getName();
//name = name.toLowerCase();
//boolean b = name.endsWith(".java");
//if(b){
// System.out.println(f);
//}
//链式编程
if(f.getName().toLowerCase().endsWith(".java")){
System.out.println(f);
}
}
}
}
}
}
三、IO概述
一切皆为字节
硬盘中的一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存(计算机只能识别0和1),都一个一个的字节(1个字节=8比特位),那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据(1,0)。
四、字节流
1.1 字节输出流的介绍
/*
java.io.OutputStream:字节输出流
此抽象类是表示输出字节流的所有类的超类。
OutputStream里边定义了所有字节输出流中共性的成员方法,所有字节输出流都可以使用
共性的成员方法:
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
public abstract void write(int b) :将指定的字节输出流。
public void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
java.io.FileOutputStream:文件字节输出流 extends OutputStream
作用:
把内存中字节写入到硬盘的文件中保存
构造方法:
FileOutputStream(File file)
FileOutputStream(String name)
参数:输出的目的地
String name:输出的目的地是一个文件的路径
File file:输出的目的地就是一个文件
构造方法的目的地:
1.会创建FileOutputStream对象
2.会根据构造方法中传递的文件路径|文件,创建一个新的空白文件
3.会把FileOutputStream对象指向创建好的文件
使用字节输出流往文件中写数据底层过程
java程序==>JVM==>操作系统(OS)==>调用系统中写数据的方法==>把数据写入到文件中
*/
1.2 字节输出流的基本使用
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节输出流的基本使用(重点)
1.创建FileOutputStream对象,构造方法中绑定要输出的目的地
2.使用FileOutputStream对象中方法write,把数据写入到文件中
3.释放资源(关闭此输出流并释放与此流相关联的任何系统资源)
*/
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
//1.创建FileOutputStream对象,构造方法中绑定要输出的目的地
//FileOutputStream fos = new FileOutputStream("w:\\day15\\a.txt");//FileNotFoundException: w:\day15\a.txt (系统找不到指定的路径。)
FileOutputStream fos = new FileOutputStream("day15\\a.txt");
//2.使用FileOutputStream对象中方法write,把数据写入到文件中
//public abstract void write(int b) 一次写一个字节到文件中
fos.write(97);
//3.释放资源(关闭此输出流并释放与此流相关联的任何系统资源)
fos.close();
}
}
1.3 字节输出流中写多个字节的方法
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
/*
字节输出流中写多个字节的方法(重点)
public abstract void write(int b) :一次写一个字节到文件中
public void write(byte[] b) :一次把字节数组中所有的字节写入到文件中
public void write(byte[] b, int off, int len) :写字节数组的一部分到文件中
int off:数组的开始索引,从哪个索引开始写
int len:写的字节个数
*/
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
//1.创建字节输出流FileOutputStream对象,构造方法中绑定输出的目的地
FileOutputStream fos = new FileOutputStream(new File("day15\\b.txt"));
//2.使用FileOutputStream对象中的方法write,把数据写入到文件中
/*
面试题
一次写一个字节,在文件中如何显示100?
*/
fos.write(49);//1
fos.write(48);//0
fos.write(48);//0
//public void write(byte[] b) :一次把字节数组中所有的字节写入到文件中
byte[] bytes = {65,66,67,68,69,70};
fos.write(bytes);//ABCDEF
/*
public void write(byte[] b, int off, int len) :写字节数组的一部分到文件中
int off:数组的开始索引,从哪个索引开始写
int len:写的字节个数
*/
fos.write(bytes,2,3);//CDE
//把字符串转换为字节数组,写入到文件中
byte[] bytes2 = "中国".getBytes();
System.out.println(Arrays.toString(bytes2));//IDEA默认使用UTF-8编码 [-28, -72, -83, -27, -101, -67] 1个中文3个字节
fos.write(bytes2);//中国
//3.释放资源
fos.close();
}
1.4 字节输出流的续写和换行
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节输出流的续写和换行(重点)
1.续写(追加写):使用两个参数的构造方法
FileOutputStream(File file, boolean append)
FileOutputStream(String name, boolean append)
参数:
File file|String name:写入数据的目的地
boolean append:续写开关
true:可以续写,使用构造方法创建对象,文件名相同的,不会创建新的文件覆盖之前同名的文件
会继续往文件的末尾写数据
false:不可以续写,使用构造方法创建对象,文件名相同,会创建一个新的空白的文件覆盖之前同名的文件
在新的文件中写数据
2.换行:使用换行符号
windows: \r\n
linux: /n
mac: /r Mac OS X开始与Linux统一
*/
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
//1.创建FileOutputStream对象,构造方法中绑定要输出的目的地和续写开关
FileOutputStream fos = new FileOutputStream("day15\\c.txt",true);
//2.使用FileOutputStream对象中的方法write,把数据写入到文件中
for (int i = 1; i <= 10; i++) {
fos.write(("你好"+i+"\r\n").getBytes());
}
//3.释放资源
fos.close();
}
}