🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!
人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习!欢迎志同道合的朋友一起加油喔🦾🦾🦾
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心
目录
2.1 字节流-InputStream / FileInputStream
3.1 字节流-OutputStream / FileOutputStream
1.File类
在java程序中操纵 文件/目录 ?怎么办?
java程序,最典型的特点,面向对象,java程序最擅长的就是操作对象,盘符上的文件/目录,将它的各种信息进行了封装,封装为一个对象,
java程序最擅长的就是操纵对象,这个对象属于 ---》File类
盘符上的文件---》封装为对象---》对象属于File类的对象--》有了这个对象,我们程序就可以直接操纵这个对象,通过这个对象获取文件的各种信息,还可以对文件进行创建 ,删除。
File概述
在java中提供了一个File类通过这个类来完成文件系统的相关操作例如:
1)列出目录中有哪些文件
2)创建文件
3)创建目录
4)删除文件
5)重命名文件
…
这个File类就描述了一个文件/目录,通过这个对象就可以实现以上的功能
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 对象代表的文件是否是一个目录 |
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.1 File类对文件进行操作
public class Test01 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//将文件封装为一个File类的对象:
File f = new File("d:\\test.txt");
File f1 = new File("d:\\test.txt");
File f2 = new File("d:/test.txt");
//File.separator属性帮我们获取当前操作系统的路径拼接符号
//在windows,dos下,系统默认用“\”作为路径分隔符 ,在unix,url中,使用“/”作为路径分隔符。
File f3 = new File("d:"+File.separator+"test.txt");//建议使用这种
//常用方法:
System.out.println("文件是否可读:"+f.canRead());
System.out.println("文件是否可写:"+f.canWrite());
System.out.println("文件的名字:"+f.getName());
System.out.println("上级目录:"+f.getParent());
System.out.println("是否是一个目录:"+f.isDirectory());
System.out.println("是否是一个文件:"+f.isFile());
System.out.println("是否隐藏:"+f.isHidden());
System.out.println("文件的大小:"+f.length());
System.out.println("是否存在:"+f.exists());
/*if(f.exists()){//如果文件存在,将文件删除操作
f.delete();
}else{//如果不存在,就创建这个文件
f.createNewFile();
}*/
System.out.println(f == f1);//比较两个对象的地址
System.out.println(f.equals(f1));//比较两个对象对应的文件的路径
//跟路径相关的:
System.out.println("绝对路径:"+f.getAbsolutePath());
System.out.println("相对路径:"+f.getPath());
System.out.println("toString:"+f.toString());
System.out.println("----------------------");
File f5 = new File("demo.txt");
if(!f5.exists()){
f5.createNewFile();
}
//绝对路径指的就是:真实的一个精准的,完整的路径
System.out.println("绝对路径:"+f5.getAbsolutePath());
//相对路径:有一个参照物,相对这个参照物的路径。
//在main方法中,相对位置指的就是:D:\IDEA_workspace\TestJavaSE
//在junit的测试方法中,相对路径指的就是模块位置
System.out.println("相对路径:"+f5.getPath());
//toString的效果永远是 相对路径
System.out.println("toString:"+f5.toString());
File f6 = new File("a/b/c/demo.txt");
if(!f5.exists()){
f5.createNewFile();
}
System.out.println("绝对路径:"+f6.getAbsolutePath());
System.out.println("相对路径:"+f6.getPath());
}
}
1.2 File类对目录进行操作
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//将目录封装为File类的对象:
File f = new File("D:\\IDEA");
System.out.println("文件是否可读:"+f.canRead());
System.out.println("文件是否可写:"+f.canWrite());
System.out.println("文件的名字:"+f.getName());
System.out.println("上级目录:"+f.getParent());
System.out.println("是否是一个目录:"+f.isDirectory());
System.out.println("是否是一个文件:"+f.isFile());
System.out.println("是否隐藏:"+f.isHidden());
System.out.println("文件的大小:"+f.length());
System.out.println("是否存在:"+f.exists());
System.out.println("绝对路径:"+f.getAbsolutePath());
System.out.println("相对路径:"+f.getPath());
System.out.println("toString:"+f.toString());
//跟目录相关的方法:
File f2 = new File("D:\\b\\b\\c");
File f3 = new File("D:\\c\\b\\c");
//创建目录:
// f2.mkdir();//创建单层目录
f2.mkdirs();//创建多层目录
//删除:如果是删除目录的话,只会删除一层,并且前提:这层目录是空的,里面没有内容,如果内容就不会被删除
f2.delete();
//查看:
String[] list = f.list();//文件夹下目录/文件对应的名字的数组
for(String s:list){
System.out.println(s); //只能输出文件名
}
System.out.println("=========================");
File[] files = f.listFiles();//作用更加广泛
for(File file:files){
//能通过对象去获取名字和路径等等
System.out.println(file.getName()+","+file.getAbsolutePath());
}
}
}
字符流和字节流
文本文件:.txt .java .c .cpp ---》建议使用字符流操作
非文本文件:.jpg, .mp3 , .mp4 , .doc , .ppt ---》建议使用字节流操作
2. 读文件
2.1 字节流-InputStream / FileInputStream
针对文件内容,使用“流对象”来进行操作。Java标准库中的流对象,从类型上分为字节流操作二进制数据的和字符流操作文本数据的。字节流中,又存在InputStream和OutputStream两个抽象类。
InputStream方法:
修饰符及返回值类型 | 方法 | 说明 |
int | read() | 读取一个字节的数据,返回 -1 代表已经完全读完了 |
int | read(byte[] b) | 最多读取 b.length 字节的数据到 b 中,返回实际读到的数 量;返回 -1 代表以及读完了 |
int | read(byte[] b, int off, int len) | 读数据到 b 数组中,从 b[ off ] 开始放,返 回实际读到的数量; -1 代表以及读完了 |
void | close() | 关闭字节流 |
InputStream只是一个抽象类,要使用还要具体的实现类,对于文件读取来说,通常使用FileInputStream,其构造方法如下:
方法名 | 说明 |
FilelnputStream (File file) | 利用File构造文件输入流 |
FilelnputStream (String name) | 利用文件路径构造文件输入流 |
🍃打开文件
InputStream inputStream = new FileInputStream("test2.txt");
- 对于这一行代码,打开文件成功后,就得到了 InputStream 对象,后续针对文件的操作,就都是通过这个对象展开的。
- 再者,我们操作硬盘不方便直接操作,在内存里构造一个和它关联的对象,操作这个对象就相当于操作硬盘数据。
上述操作对象相当于操作硬盘数据,就类似于遥控器,我们开空调的时候,不可能每次借助梯子爬上去,用手摁下空调开关,而是通过空调遥控器去操作空调。
🍃关闭文件
inputStream.close();
// 此处会抛出一个 IOException,对于打开文件抛出的文件找不到异常,IOException是其父类
为什么要关闭文件??
关闭文件主要是为了释放文件描述符表资源。
文件描述符表,这个表就相当于是个数组,这个数组的下标就称为 "文件描述符",每次打开一个文件,都会在文件描述符表中占据一个位置;每次关闭文件,都会释放一个位置。并且文件描述符表,是存在上线的,如果一个进程,一直在打开文件,没有释放,此时就会导致我们的进程在进行后续打开文件操作的时候,就会打开文件失败!!
🍃读取文件
🍔read() 代码示例
public static void main(String[] args) throws IOException {
// 1.打开文件
InputStream inputStream = new FileInputStream("test2.txt");
// 2.读取文件
while(true) {
int b = inputStream.read();
if(b == -1) {
// 文件读完了
break;
}
// 因为 ASCII 码值以字节为单位存储,所以这里输出的是每个单词对应的 ASCII 码值
System.out.println(b); // hello 对应的 ASCII 码值
}
// 3.关闭文件
inputStream.close();
}
🍔read(byte[] b)代码示例
public static void main(String[] args) throws IOException {
// 1.打开文件
InputStream inputStream = new FileInputStream("test2.txt");
// 2.读取文件
byte[] buf = new byte[1024];
// 返回的长度(字节)
int len = inputStream.read(buf);
System.out.println(len);
for(int i = 0; i < len; i++) {
System.out.println(buf[i]);
}
// 3.关闭文件
inputStream.close();
}
注意: 如果是读取中文,UTF8 的编码格式,一个汉字占3个字节。
如果要想读取中文在控制台,字节流只能通过指定编码格式,就比较麻烦。例如以下代码:
public static void main(String[] args) throws IOException {
// 1.打开文件
InputStream inputStream = new FileInputStream("test2.txt");
// 2.读取文件
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
String s = new String(buf, 0, len, "UTF8");
System.out.println(s);
// 3.关闭文件
inputStream.close();
}
2.2 字符流-Reader / FileReader
这里的方法和上面的 InputStream 相似就不过多介绍了。
🍔读取中文代码示例
public static void main(String[] args) throws IOException {
// 字符流
Reader reader = new FileReader("test2.txt");
char[] buffer = new char[1024];
int len = reader.read(buffer);
for(int i = 0; i < len; i++) {
System.out.println(buffer[i]);
}
reader.close();
}
虽然字符流读取中文比纯字节流好使一些,但还是不够方便。对于文本文件,还有更简单的写法。
2.3 通过 Scanner 进行字符读取
🍁Scanner 构造方法
构造方法 | 说明 |
Scanner(InputStream is, String charset) | 使用 charset 字符集进行 is 的扫描读取 (也可以不指定编码格式,使用默认编码格式) |
代码示例
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("test2.txt");
Scanner scanner = new Scanner(inputStream);
// 想读什么类型就用 scanner 去调用什么
String s = scanner.next();
System.out.println(s);
inputStream.close();
}
2.4 关闭资源的优化
我们在前面字节流读取中文的代码中,发现如果在 read() 读文件的过程中出现异常,就可能导致 close() 执行不到,按照我们以前的思路,使用 try...catch...finally,将关闭资源放在 finally 中。
public static void main(String[] args) {
InputStream inputStream = null;
try {
// 打开文件(字节流)
inputStream = new FileInputStream("test2.txt");
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
// 读取中文
String s = new String(buf, 0, len, "UTF8");
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果这样做的话,我们的代码显得又臭又长,更推荐的做法是以下做法:
public static void main(String[] args) {
try (InputStream inputStream = new FileInputStream("test2.txt")) {
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
// .........
} catch (IOException e) {
e.printStackTrace();
}
}
这种语法机制叫做 try with resources,这个操作就会在 try 执行结束后,自动调用 inputStream 的 close 方法(实现 Closeable 接口的类才能这样做)。
3.写文件
3.1 字节流-OutputStream / FileOutputStream
【方法】
修饰 符及 返回 值类 型 | 方法 | 说明 |
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。
🍃代码示例
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("test2.txt")) {
// 方法一
/* outputStream.write('h');
outputStream.write('e');
outputStream.write('l');
outputStream.write('l');
outputStream.write('o'); */
// 方法二
String s = " hello java";
outputStream.write(s.getBytes());
// 把旧的文件内容清空,重新去写
} catch (IOException e) {
e.printStackTrace();
}
}
注意:每次重新写的时候,都会把旧的文件内容清空掉,重新去写。
但是这种原生字节流的写文件方法,用起来还是不方便。
3.2 字符流-Writer / FileWriter
🍃代码示例
public static void main(String[] args) {
try (Writer writer = new FileWriter("test2.txt")) {
// 能写字符串,就很方便
writer.write("hello world");
} catch (IOException e) {
e.printStackTrace();
}
}
我们的这个字符流中的 Writer 还能写字符串,就很方便。还有一种方式 -- PrintWriter ,它提供了更丰富的写。
PrintWriter 代码示例
public static void main(String[] args) {
try (OutputStream outputStream = new FileOutputStream("test2.txt")) {
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println("hello");
printWriter.println("你好");
printWriter.printf("%d: %s\n", 1, "Java");
// println 需要搭配 flush 使用
printWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
🍃这里要注意 PrintWrite 是自带缓冲区的,缓冲区是时候会被刷新到硬盘中呢?
🍃1.缓冲区满了;2.显示调用 flush 方法
所以我们在调用 println 写文件的时候,务必记得 flush 刷新
3. System类的使用
【1】System的属性:
System.in : “标准”输入流。---》默认情况下 从键盘输入
System.out :“标准”输出流。 ---》默认情况下,输出到控制台。
【2】System.in :“标准”输入流。---》默认情况下 从键盘输入
public class Test01 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) throws IOException {
//得到的是标准的输入流:--》从键盘输入:
//InputStream in = System.in;
//调用方法:
//int n = in.read();//read方法等待键盘的录入,所以这个方法是一个阻塞方法。
//System.out.println(n);
//以前案例:从键盘录入一个int类型的数据:
//从上面的代码证明,键盘录入实际上是:System.in
//形象的理解:System.in管,这个管怼到键盘上去了,所以你从键盘录入的话,就从这个管到程序中了
//Scanner的作用:扫描器:起扫描作用的,扫键盘的从这根管出来的数据
/*Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.println(i);*/
//既然Scanner是扫描的作用,不一定非得扫 System.in进来的东西,还可以扫描其他管的内容:
Scanner sc = new Scanner(new FileInputStream(new File("d:\\Test.txt")));
while(sc.hasNext()){
System.out.println(sc.next());
}
}
}
【3】System.out : 返回的输出流 、 打印流(PrintStream)
public class Test02 {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//写到控制台:
PrintStream out = System.out;
//调用方法:
out.print("你好1");//直接在控制台写出,但是不换行
out.print("你好2");
out.print("你好3");
out.print("你好4");
out.println("我是中国人1");//直接在控制台写出,并且换行操作
out.println("我是中国人2");
out.println("我是中国人3");
out.println("我是中国人4");
System.out.println("你是");
System.out.print("中国人");
}
}
4.try-with-resource语句
try-with-resources
是Java 7中引入的一个特性,它是为了简化在程序中使用资源(例如文件、网络连接等)的管理。在Java程序中,资源的正确关闭非常重要,因为资源泄漏可能导致性能问题、程序错误或其他问题。try-with-resources
语句确保在代码块执行完毕后自动关闭资源,无论代码执行过程中是否发生异常。
try-with-resources
语句实现自动关闭资源的方式是通过在资源实现java.lang.AutoCloseable
或java.io.Closeable
接口的情况下,确保close()
方法被调用。这两个接口都包含一个close()
方法,它们的实现负责释放资源。
try-with-resources
语句的基本结构如下:
try (ResourceType resource = new ResourceType()) {
// 使用资源的代码
} catch (Exception e) {
// 处理异常的代码
}
当程序执行到
try
语句块结束时,如果resource
实现了AutoCloseable
或Closeable
接口,那么close()
方法将被自动调用。这确保了无论try
块中是否抛出异常,资源都会被正确关闭。因此,
try-with-resources
语句可以自动关闭资源,主要是因为它依赖实现AutoCloseable
或Closeable
接口的资源,使得在try
语句块结束时自动调用close()
方法。这简化了资源管理,降低了资源泄漏和相关问题的风险。注意:如果一个资源没有实现
AutoCloseable
或Closeable
接口,那么try-with-resources
语句将无法自动关闭该资源。在这种情况下,你需要在代码中手动管理资源的关闭。