【JavaEE】文件操作IO之File 、InputStream、OutputStream 用法详解
目录
1.利用 OutputStreamWriter 进行字符写入
一、文件概念
(1)文件定义与组成
狭义上:针对硬盘这种持久化存储的I/O设备,当进行数据保存时,往往不是保存成一个整体,而是独立成一个个的单位进行保存,这个独立的单位就被抽象成文件的概念。
每个文件都有属于它自己的,不是内容的一些信息。例如文件名、文件类型、文件大小,不作为文件数据。这些信息就称作文件的元信息。
(2)文件的树形结构组织和目录
文件的系统管理:是按照层级结构进行组织,就是数据结构中所提到的树形结构。
目录:一种专门用来存放管理信息的特殊文件。也称文件夹。
(3)文件路径
文件的绝对路径(absolute path):从树型结构的角度来看,树中的每个结点都可以被一条从根开始,一直到达的结点的路径所描述,这种描述方式就被称为文件的绝对路径。绝对路径是固定的,不会发生改变。
例如:以Windows操作系统为例,绝对路径就是以盘符为开头。C盘为根目录,从C盘开始找到存放jdk的文件。C:\Program Files\Java\jdk1.8.0_131。
文件的相对路径(relative path):从任意结点出发,进行路径的描述,而这种描述方式就被称为相对路径,相对于当前所在结点的一条路径。相对路径一定要有基准路径。.表示当前路径。..表示当前路径的父目录(上级目录)。
例如:基准路径是C:\Program Files\Java。./表示的路径就代表C:\Program Files\Java。
基准路径是C:\Program Files\Java。../表示的路径就代表C:\Program Files。
/斜杆和\反斜杠小贴士:
对于大部分操作系统,路径的分隔符都是/斜杠 ,但是对于Windows来说使用的是\反斜杠。Windows最早的系统是基于Dos开发的,Dos系统最早的时候,/斜杆已经有了其他用途,就接着了反斜杠\。
后期Windows意识到大多数操作系统都是斜杠/,当编程的时候也会出现问题。例如D:\taa.txt,\t会被当成制表符,就得使用\\t。随着逐渐发展,斜杠和反斜杠都能被识别了。一个注意点是当人为输入/时,Windows输出的还是\。
(4)文件分类
一般简单的划分为文本文件和二进制文件,分别指代保存被字符集编码的文本和按照标准格式保存的非被字符集编码过的文件。简而言之,能看懂的就是文本文件,一堆乱码的就是二进制文件。
(5)文件操作
Java中对于文件的操作可以分为两类,一是文件系统相关的操作:包括1)创建目录2)删除目录3)创建文件4)删除文件5)列出目录下的文件6)重命名。二是文件内容相关操作:包括1)读文件内容2)写文件内容。对于文件内容的操作,分为二进制文件和文本文件。
二、文件操作File类
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。注意:有 File 对象,并不代表真实存在该文件。根据一个路径,创建一个File文件,假如这个路径不存在,这个文件也就不存在,但是File对象是存在的。
(1)File类中的属性
修饰符及类型 | 属性 | 说明 |
static String | pathSeparator | 依赖于系统的路径分隔符,String 类型的表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char 类型的表示 |
与系统有关,不同的系统分割符不同。
(2)File类的构造方法
签名 | 说明 |
File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者 相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用 路径表示 |
(3)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.get系列用法代码实例
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.getParent()); System.out.println(file.getName()); System.out.println(file.getPath()); System.out.println(file.getAbsolutePath()); System.out.println(file.getCanonicalPath()); }}
运行结果:
..
hello-world.txt
..\hello-world.txt
D:\代码练习\文件示例1\..\hello-world.txt
D:\代码练习\hello-world.txt
import java.io.File;import java.io.IOException;public class Main { public static void main(String[] args) throws IOException { File file = new File("file.txt"); // 并不要求该文件真实存在 System.out.println(file.getPath()); System.out.println(file.getAbsolutePath()); System.out.println(file.getCanonicalPath()); }}
运行结果:
file.txt
D:\代码练习\文件示例1\file.txt
D:\代码练习\文件示例1\file.txt
import java.io.File;import java.io.IOException;public class Main { public static void main(String[] args) throws IOException { File file = new File("./file.txt"); // 并不要求该文件真实存在 System.out.println(file.getPath()); System.out.println(file.getAbsolutePath()); System.out.println(file.getCanonicalPath()); }}
运行结果:
file.txt
D:\代码练习\文件示例1\.\file.txt
D:\代码练习\文件示例1\file.txt
这里的基准路径是D:\代码练习\文件示例1 ,相对路径是.\file.txt。绝对路径就是基准路径+相对路径。
在ideal里面运行,基准路径是项目的工作路径。用不同的方式运行,同样一份的代码,基准路基也是不一样的。
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()); System.out.println(file.isDirectory()); System.out.println(file.isFile()); System.out.println(file.createNewFile()); System.out.println(file.exists()); System.out.println(file.isDirectory()); System.out.println(file.isFile()); System.out.println(file.createNewFile()); }}
运行结果:
false
false
false
true
true
false
true
false
3.普通文件的删除
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()); System.out.println(file.createNewFile()); System.out.println(file.exists()); System.out.println(file.delete()); System.out.println(file.exists()); }}
运行结果:
false
true
true
true
false
4.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()); System.out.println(file.createNewFile()); System.out.println(file.exists()); file.deleteOnExit(); System.out.println(file.exists()); }}
运行结果:
false
true
true
true程序运行结束后,文件还是被删除了
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-dir"); // 要求该目录不存在,才能看到相同的现象 System.out.println(dir.isDirectory()); System.out.println(dir.isFile()); System.out.println(dir.mkdir()); System.out.println(dir.isDirectory()); System.out.println(dir.isFile()); }}
运行结果:
false
false
true
true
false
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 和 somedir 都不存在 System.out.println(dir.isDirectory()); System.out.println(dir.isFile()); System.out.println(dir.mkdir()); System.out.println(dir.isDirectory()); System.out.println(dir.isFile()); }}
运行结果:
false
false
false
false
falsemkdir() 的时候,如果中间目录不存在,则无法创建成功; mkdirs() 可以解决这个问题。
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 和 somedir 都不存在 System.out.println(dir.isDirectory()); System.out.println(dir.isFile()); System.out.println(dir.mkdirs()); System.out.println(dir.isDirectory()); System.out.println(dir.isFile()); }}
运行结果:
false
false
true
true
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()); System.out.println(dest.exists()); System.out.println(file.renameTo(dest)); System.out.println(file.exists()); System.out.println(dest.exists()); }}
运行结果:
true
false
true
false
true
三、文件操作InputStream
(1)InputStream概述
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() | 关闭字节流 |
(2)FileInputStream概述
InputStream 只是一个抽象类,要使用还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,本文只关心从文件中读取,所以使用 FileInputStream。
1.FileInputStream 构造方法
构造方法:
签名 | 说明 |
FileInputStream(File file) | 利用 File 构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
代码实例一:
将文件完全读完的两种方式。相比较而言,后一种的 IO 次数更少,性能更好
import java.io.*;// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "Hello" 的内容public class Main { public static void main(String[] args) throws IOException { try (InputStream is = new FileInputStream("hello.txt")) { while (true) { int b = is.read(); if (b == -1) { // 代表文件已经全部读完 break; } System.out.printf("%c", b); } } }}
import java.io.*;// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "Hello" 的内容public class Main { public static void main(String[] args) throws IOException { try (InputStream is = new FileInputStream("hello.txt")) { byte[] buf = new byte[1024]; int len; while (true) { len = is.read(buf); if (len == -1) { // 代表文件已经全部读完 break; } for (int i = 0; i < len; i++) { System.out.printf("%c", buf[i]); } } } }}
代码实例二:
文件中填写中文。写中文的时候使用 UTF-8 编码。hello.txt 中填写 "你好中国"
“你好中国”这几个中文的 UTF-8 编码后长度刚好是 3 个字节和长度不超过 1024 字节的现状,但这种方式并不是通用的。
import java.io.*;// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容public class Main { public static void main(String[] args) throws IOException { try (InputStream is = new FileInputStream("hello.txt")) { byte[] buf = new byte[1024]; int len; while (true) { len = is.read(buf); if (len == -1) { // 代表文件已经全部读完 break; } // 每次使用 3 字节进行 utf-8 解码,得到中文字符 // 利用 String 中的构造方法完成 // 这个方法了解下即可,不是通用的解决办法 for (int i = 0; i < len; i += 3) { String s = new String(buf, i, 3, "UTF-8"); System.out.printf("%s", s); } } } }}
2.利用Scanner进行读取
由代码实例二可知,对字符类型直接使用 InputStream 进行读取是非常麻烦且困难的,所以,我们使用Scanner 类。
构造方法:
构造方法 | 说明 |
Scanner(InputStream is, String charset) | 使用 charset 字符集进行 is 的扫描读取 |
代码示例:
import java.io.*;import java.util.*;// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容public class Main { public static void main(String[] args) throws IOException { try (InputStream is = new FileInputStream("hello.txt")) { try (Scanner scanner = new Scanner(is, "UTF-8")) { while (scanner.hasNext()) { String s = scanner.next(); System.out.print(s); } } } }}
四、文件操作OutputStream
(1)OutputStream概述
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(刷新)操作,将数据刷到设备中。 |
(2)FileOutputStream概述
OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。本文只关心写入文件中,所以使用 FileOutputStream。
1.利用 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'); // 不要忘记 flush os.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); // 不要忘记 flush os.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); // 不要忘记 flush os.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); // 不要忘记 flush os.flush(); } }}
代码实例五:
import java.io.*;public class Main { public static void main(String[] args) throw try (OutputStream os = new FileOutputStr String s = "你好中国"; byte[] b = s.getBytes("utf-8"); os.write(b); // 不要忘记 flush os.flush(); } }}
2.利用 PrintWriter 找到熟悉的方法
PrintWriter 类中提供了我们熟悉的 print、println、printf 等方法。故而将 OutputStream 处理下,使用PrintWriter 类来完成输出。
第一步:OutputStream os = ...;
第二步:OutputStreamWriter osWriter = new OutputStreamWriter(os, "utf-8");告知的字符集编码的类型是 utf-8 。第三步:PrintWriter writer = new PrintWriter(osWriter); 使用 writer 提供的各种方法。
例如:
writer.print("Hello");
writer.println("你好");
writer.printf("%d: %s\n", 1, "没什么");
第四步:记得flush。writer.flush();
代码实例:
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(); } } } }}
来源地址:https://blog.csdn.net/m0_63372226/article/details/128843105
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341