File类
File有文件的意思,是唯一与文件有关的类。File类就是文件和目录路径名的抽象表示,通俗来说一个File对象就可以表示一个文件的抽象。
此类的定义方式如下
public class File extends Object implements Serializable,Comparable<File>
FIle类中的常量
No. | 常量名称 | 类型 | 描述 |
---|---|---|---|
1 | public static final String pathSeparator | 常量 | 表示路径的分隔符(windows是:";"),方便起见用字符串表示 |
2 | public static final String sparator | 常量 | 表示路径的分隔符(windows是:"\"),方便起见用字符串表示 |
File类中的构造方法
No. | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | File(File parent,String child) | 构造 | 从父抽象路径名和子路径名字符串创新的File实例 |
2 | Flie(String pathname) | 构造 | 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例 |
3 | File(String parent,String child) | 构造 | 从父路径名字符串和子路径名字符串创建新的File实例 |
4 | File(URI uri) | 构造 | 通过将给定的file:URL转换为抽象路径名来创建新的File实例 |
File类中的主要操作方法
No. | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public boolean creatNewFile() | 普通 | 当且仅当具有此名称的文件不存在时,创建由此抽象路径命名的新空文件 |
2 | public boolean delete() | 普通 | 删除由此抽象路径名表示的目录或文件 |
3 | public boolean is Directory() | 普通 | 判断此文件是否为目录 |
4 | public long length() | 普通 | 返回文件的大小(字节表示) |
5 | public String[] list() | 普通 | 返回一个字符串数组,用于命名此抽象路径名表示的目录中的文件和目录。 |
6 | public boolean exists() | 普通 | 判断文件是否存在 |
7 | public FIle[] listFiles() | 普通 | 列出指定目录的全部内容 |
8 | public boolean mkdir() | 普通 | 创建一个目录 |
9 | public boolean renameTo(File dest) | 普通 | 重命名次抽象路径所表示的文件 |
10 | public String getAbsolutePath() | 普通 | 获取该文件的绝对路径 |
11 | public String getParent() | 普通 | 获取该文件的父文件夹的绝对路径 |
创建文件实例:
import java.io.File;
import java.io.IOException;
public class Text1 {
public static void main(String[] args) throws IOException {
File f = new File("D://1.txt"); //创建一个file对象,这个对象代表,D盘下的1.txt文件。
boolean l = f.createNewFile(); //调用createNewFile()方法创建这个文件夹,并将结果返回给l
System.out.println(l);
boolean k = f.createNewFile(); //再创建一次
System.out.println(k);
}
}
输出:
true
false
输出true,表示D盘下原本没有1.txt文件,创建成功。
输出false,表示D盘下已存在1.txt这个文件,创建失败
文件创建结果:
文件重命名实例:
public class Text1 {
public static void main(String[] args) throws IOException {
File f = new File("D:\\1.txt"); //创建f对象代表1.txt文件
File newf = new File("D:\\5.txt"); //创建newf对象代表5.txt文件
f.renameTo(newf); //调用f的renameTo方法传入newf对象,1.txt重命名为5.txt
//(本质:创建5.txt,将1.txt的内容复制到5.txt,删除1.txt)
}
}
遍历文件实例:
以“谷歌浏览器下载”为例,遍历该文件夹,输出所以pdf文件的绝对路径
代码:
import java.io.File;
import java.io.IOException;
public class Text1 {
public static void main(String[] args) throws IOException {
File file = new File("D:\\谷歌浏览器下载"); //实例化一个File对象,代表D盘下的谷歌浏览器下载文件夹
File[] files = file.listFiles();//将文件夹的子文件依次实例化并存入File对象数组
listFiles(files); //调用文件遍历方法,传入数组
}
//文件遍历方法
public static void listFiles(File[] files){
if(files != null && files.length > 0){ //判断对象数组是否为空,数组长度是否为零
for (File f:files) { //遍历数组
if(f.isFile()){ //如果该对象是文件
if (f.getName().endsWith(".pdf")){ //如果该文件后缀是.pdf
System.out.println("找到了一个pdf文件:"+f.getAbsolutePath());//输出文件的绝对路径
}
}else{ //如果是文件夹
File[] files2 = f.listFiles(); //将文件夹的子文件依次实例化并存入数组
listFiles(files2); //递归
}
}
}
}
}
输出
找到了一个pdf文件:D:\谷歌浏览器下载\IDEA的下载与安装使用.pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-002-测试题-OOP.pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10101001-支线任务-语法训练 - 入门与学习方式(环境搭建与笔记整理).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10101002-支线任务-语法训练 - 小王的面试(基础语法).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10101006-支线任务-语法训练 - 选队长的游戏(数组).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10201-主线任务-快递e栈-面向对象.pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10201001-支线任务-面向对象 - 面向对象基础训练(面向对象基础) (1).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10201001-支线任务-面向对象 - 面向对象基础训练(面向对象基础) .pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10201003-支线任务-面向对象 - 面向对象进阶训练(面向对象高级) .pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10201004-支线任务-面向对象 - 猜拳游戏(面向对象) .pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10202-主线任务-快递e栈-更换IDEA (1).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10202-主线任务-快递e栈-更换IDEA.pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10203001-支线任务-异常处理 - 快递管理(异常处理) (1).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10203001-支线任务-异常处理 - 快递管理(异常处理).pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10301-主线任务-快递e栈-核心类库.pdf
找到了一个pdf文件:D:\谷歌浏览器下载\XZK-Java教学-10301001-支线任务-String类.pdf
大伙可以运用这个知识点自己写一个垃圾清理软件,只需再添加一个删除语句即可。但是,如果你还不是很了解文件的话,建议做好重装系统的准备hhhhhh。
相对路径和绝对路径
绝对路径:从盘符开始,是一个完整的路径,例如D:\1.txt
相对路径:在JAVA代码中是相对于项目目录路径,这是一个不完整的便捷路径,在java开发中很常用。例如:a.txt
例
import java.io.File;
import java.io.IOException;
public class Text1 {
public static void main(String[] args) throws IOException {
File f1 = new File("D:\\1.txt");//绝对
File f2 = new File("a.txt"); //相对
System.out.println("f1的路径:"+f1.getAbsolutePath());
System.out.println("f2的路径:"+f2.getAbsolutePath());
}
}
输出
f1的路径D:\1.txt
f2的路径D:\IDEA projects\TEXT1\a.txt //D:\IDEA projects\TEXT1是我项目的路径,每个人都有各自的项目路径,不必追求相同
IO流
概述:可以将数据传输操作,看做一种数据的流动,按照流动的方向分为输入Input和输出Output。JAVA中的IO操作主要是java.io包下的一些常用类的使用,通过这些类对数据进行读取(输入流Input)和写出(输出流Output)
IO流分类:
按照流动方向:输入流、输出流
按照流动的数据类型:字节流、字符流
输入有N种方式,输出也有N种方式,他们是按照类的结构划分 ,以下是他们的顶级父类:
字节流
- 输入流:InputStream
- 输出流:OutputStream
字符流
- 输入流:Reader
- 输出流:Writer
字节输出流-OutputStream
一切皆字节:计算机中的任何数据(文本、图片、视频、音乐)都是以二进制存储的。在数据传输时,也都是以二进制的形式存储的。后续学习的任何流,在传输时底层都是二进制。
这是一个抽象类,此抽象类是表示输出字节流的所有类的顶级父类
该类定义如下
public abstract class OutputStream extends Object implements Closeable, Flushable
该类的所以方法
No. | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public void close() | 普通 | 关闭此输出流并释放与此流关联的所以系统资源 |
2 | public void flush() | 普通 | 刷新此输出流并强制写出任何缓冲的输出字节 |
3 | public static OutputSteram nullOutputStream() | 普通 | 返回一个新的OutputSteram,它丢弃所以字节 |
4 | public void write(byte[] b) | 普通 | 将b.length字节从指定的字节数组写入此输出流 |
5 | public void write(byte[] b,int off,int len) | 普通 | 将从下标off开始的指定字节数组中的len字节写入此输出流 |
6 | public abstract void write(int b) | 抽象 | 将制定的字节写出此输出流 |
FileOutputStream
输出实例一
import java.io.FileOutputStream;
import java.io.IOException;
public class Text1 {
public static void main(String[] args) throws IOException {
FileOutputStream f = new FileOutputStream("D:\\1.txt"); //创建一个输出流对象,可以理解为一个向文件输出东西的管道
f.write(65); //输出字节65
f.close(); //释放资源
System.out.println("已经写出");
}
}
输出
已经写出
此时我们的D盘下会自动生成1.txt文件:
为什么我们写出65会变成A ?因为按照ASCII码,65字节对应的就是字符A
简而言之:字符A的ASCII码是65 字节(Byte)
输出案例二
import java.io.FileOutputStream;
import java.io.IOException;
public class Text1 {
public static void main(String[] args) throws IOException {
FileOutputStream f = new FileOutputStream("D:\\1.txt");
byte[] bytes = {65,66,67}; //给一个字节数组
f.write(bytes); //写出这个字节数组
f.close();
System.out.println("已经写出");
}
}
输出案例三
import java.io.FileOutputStream;
import java.io.IOException;
public class Text1 {
public static void main(String[] args) throws IOException {
FileOutputStream f = new FileOutputStream("D:\\1.txt",true); //传入true ,证明不清空文件内容,继续追加
byte[] bytes = {65,66,67};
f.write(bytes);
f.close();
System.out.println("已经写出");
}
}
输出案例四
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class Text1 {
public static void main(String[] args) throws IOException {
FileOutputStream f = new FileOutputStream("D:\\1.txt");
byte[] bytes = {65,66,67,68};
f.write(bytes,1,2); //从1下标开始往后写出,总共写2位
f.close();
System.out.println("已经写出");
}
}
字节输入流-InputStream
此抽象类是表示输入字节流的所有类的顶级父类。定义如下
public abstract class InputStream extends Object implements Closeable
此类的方法如下
No. | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public int available() | 普通 | 返回可以从此输入流中无阻塞地读取(或跳过)的字节数的估计值,可以使0,或者在检测到流结束时为0 |
2 | public void close() | 普通 | 关闭此输入流并释放与改流关联的所有系统资源 |
3 | public mark(int readlimit) | 普通 | 标记此输入流的当前位置 |
4 | public static InputStream boolean markSupported() | 普通 | 返回一个不读取任何字节的新InputStream |
5 | public abstract int read() | 抽象 | 从输出流中读取下一个数据字节 |
6 | public int read(byte[] b) | 普通 | 从输入流中读取一些字节数并将它们存储到缓冲区数组b |
7 | public int read(byte[] b, int off, int len) | 普通 | 读入一个字节数组,从off开始len个数据 |
8 | public byte[] readAllBytes() | 普通 | 从输入流中读取所以剩余字节。 |
9 | public int readNBytes(byte[] b, int off, int len) | 普通 | 从输入流中读取请求的字节数到给定的字符数组中 |
10 | public byte[] readNBytes(int len) | 普通 | 从输出流中读取指定的字节数 |
11 | public void reset() | 普通 | 将此流重新定位到上次在此输入流上调用mark方法时的位置 |
12 | public long skip(long n) | 普通 | 跳过并丢弃此输入流中的n字节数据 |
13 | public transferTo(OutputStream out) | 普通 | 从该输入流中读取 所以字节,并按读取顺序将字节写入给定的输出流 |
14 | public boolean markSupported() | 普通 | 测试此输入流是否指出mark和reset方法 |
FileInputStream
此类是InputStream的子类
写入文件实例一:
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\1.txt"); //实例化文件输入流对象,并指定文件1.txt
while(true){
byte b = (byte)fis.read(); //读入一个字节,赋值给b
if(b == -1){
break; //如果读取到-1,证明文件已被读完,退出循环
}
System.out.println((char)b); //输出该字节代表的字符
}
}
}
输出
A
B
C
D
E
F
G
写入文件实例二及其问题:
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\1.txt");
byte[] b = new byte[10]; //定义一个是个长度的字节数组
fis.read(b); //读入数据直到b存满
System.out.println(new String(b)); //输出转化为字符串的b
fis.read(b); //重复
System.out.println(new String(b));
fis.read(b);
System.out.println(new String(b));
fis.close();
}
}
输出
ABCDEFGHIJ
KLMNOPQRST
UVWXYZQRST
我们观察到输出结果好像与我们的预期不太符合,按道理最后依次输出到Z后面就没有了,可为什么会给我们补上了。原因是后四位是上一次存入数组的旧数据,最后一次读入只将前六位覆盖了,而最后四个没有覆盖,仍然是之前的数据。
解决办法是:获取每次读取到的字节数,只输出该字节数个字符串即可。
修改代码
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\1.txt");
byte[] b = new byte[10];
int len = fis.read(b); //获取读取的字节的数量 10
System.out.println(new String(b,0,len)); //表示从0下标开始,读取len个字符串
len = fis.read(b); //10
System.out.println(new String(b,0,len));
len = fis.read(b); //6
System.out.println(new String(b,0,len));
fis.close();
}
}
输出
ABCDEFGHIJ
KLMNOPQRST
UVWXYZ
注:我们更多使用字节数组来读数据
字节流读取文字问题
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\1.txt");
byte[] b = new byte[10];
fis.read(b);
String s = new String(b);
System.out.println(s);
fis.close();
}
}
输出
锄禾日�
我们发现只读取了三个字,后面加一个乱码,这是因为“当”字还没有读取完字节数组就已经装满。导致不完整的显示,当然,我们可以通过增大字节数组容量解决该问题,那如果文字量非常巨大,那么通过增加字节数组的容量解决问题太过麻烦。所以我们读取文字的时候,一般使用字符流。
字符输出流-Writer
输出实例:
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
Writer w = new FileWriter("D:\\1.txt",true);
w.write("锄禾日当午");
w.close();
}
}
结果
字符输入流-Reader
输入实例一:输入单个字符
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
Reader r = new FileReader("D:\\1.txt");
char c =(char)r.read();
System.out.println(c);
r.close();
}
}
输出
锄
输入实例二:输入一组字符及其问题
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
Reader r = new FileReader("D:\\1.txt");
char[] c = new char[100];
r.read(c);
String s = new String(c);
System.out.println(s);
System.out.println(s.length());
r.close();
}
}
输出
锄禾日当午,汗滴禾下土
100
此时我们会发现,明明就只有11个字符,为什么字符串的长度是100?因为我们创建的字符数组,长度是100,并且是100个初始值,也就是空格,那么我们拼接到字符串的时候,空格也拼接过来了。
解决办法
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
Reader r = new FileReader("D:\\1.txt");
char[] c = new char[100];
int len = r.read(c);
String s = new String(c,0,len);
System.out.println(s);
System.out.println(s.length());
r.close();
}
}
输出
锄禾日当午,汗滴禾下土
11
定义一个变量len记录下存了读取了多少个字符,拼接字符串时只拼接前len个字符即可。
flush刷新管道
flush的功能是清空缓存区并将缓存区的内容全部写出到文件,而我们平时没有调用flush方法,内容也被写出了,那是因为我们的close方法,其实也是调用了flush方法的
来看一个例子
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
Writer w = new FileWriter("D:\\1.txt");
w.write("锄禾日当午");
}
}
结果
内容没有被写入文件
再看
import java.io.*;
public class Text1 {
public static void main(String[] args) throws IOException {
Writer w = new FileWriter("D:\\1.txt");
w.write("锄禾日当午");
w.flush();
}
}
结果
由此可得,当我们需要利用循环向文件写内容时,需要在循环体最后加上一句flush。这样就可以保证每次循环都向文件写入了数据。
转换流-字节流转换(装饰)为字符流
当我们要从网上获取数据时,拿到的是一个字节流,不太好获取文字,那么我们就可以进行流转换,转成字符流,就可以方便获取文字
以下拿字节输入流转字符输出流为例,输出流同理
FileInputStream fis = new FileInputStream("D:\\1.txt");//假设这是你拿到的一个字节输入流
InputStreamReader isr = new InputStreamReader(fis);//转化为字符输入流
缓存流——BufferedReader/BufferedWriter
可以一次读取或写入一行的缓存字符流
例:缓存输入流
import java.io.*;
public class Text2 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("1.txt");
BufferedReader br = new BufferedReader(fr);
br.readLine();
br.close();
}
}
例:缓存输出流
import java.io.*;
public class Text2 {
public static void main(String[] args) throws IOException {
FileWriter fr = new FileWriter("1.txt");
BufferedWriter bw = new BufferedWriter(fr);
bw.write("123");
bw.newLine();
bw.close();
}
}
try-with-resources
当我们文件IO时发生异常,并且try处理时,我们会发现如上图所示的问题。我们都知道流用完之后都要close关闭释放资源,那么在处理异常时,将close语句放到finally块里是最为合理的,但是我们发现finally块无法调用try块里创建的对象。此时利用try语句的新语法可以解决该问题。
我们可以在try块内创建对象,这样的话,程序会在try/catch过后,自动执行该对象的close方法。
注意:想要完成这个操作的类,必须实现Closeable或者AutoCloseable接口。Closeable接口继承了AutoCloseable接口,AutoCloseable接口内定义了一个抽象方法close()。也就是说,所有拥有close()方法的类,都实现可Closeable或AutoCloseable接口。
倘若,从外部传入了一个对象,那么此时我们无法在try的括号里new这个对象,那么怎么办,在JDK9时,进行了优化
例
直接将对象名放入括号内即可,如果要实现多个流对象自动关闭,那么以 ";" 隔开。
刚才我们说,只要是实现了Closeable接口,并且实现了其中的close抽象方法,那么该类就可以在try后自动调用close,那么我们自己来写一个类,实现一下Closeable接口玩玩看。
import java.io.*;
public class Text2 {
public static void main(String[] args) throws IOException {
Book b = new Book();
try(b){
}catch (Exception e){
}
}
static class Book implements Closeable{
@Override
public void close() throws IOException {
System.out.println("close方法被调用了");
}
}
}
运行结果
close方法被调用了