Java 基础语法Java 的文件操作
Posted 吞吞吐吐大魔王
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 基础语法Java 的文件操作相关的知识,希望对你有一定的参考价值。
文章目录
Java 操作文件包括了两个层面:
- 在文件系统的层面上来操作文件,包括创建文件、删除文件、创建目录、拷贝文件等等。
- 操作文件里保存的数据,包括读文件、写文件。
1. 在文件系统层面操作文件
1.1 File 类介绍
Java 中通过 java.io.File
类来对一个文件(包括目录)进行抽象的描述。不过有 File 对象,并不代表对应的文件真实存在。
1.2 File 常见属性
属性 | 修饰符及类型 | 说明 |
---|---|---|
pathSeparator | static String | 依赖于系统的路径分隔符,String 类型的表示 |
pathSeparator | static char | 依赖于系统的路径分隔符,char 类型的表示 |
1.3 File 构造方法
构造方法 | 说明 |
---|---|
File(File parent, String child) | 根据父目录+孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, String child) | 根据父目录路径+孩子文件路径,创建一个新的 File 实例 |
1.4 File 常用方法
方法 | 返回值类型 | 说明 | 注意 |
---|---|---|---|
getParent() | String | 返回 File 对象的父目录文件路径 | |
getName() | String | 返回 File 对象的纯文件名称 | |
getPath() | String | 返回 File 对象的文件路径 | |
getAbsolutePath() | String | 返回 File 对象的绝对路径 | |
getCanonicalPath() | String | 返回 File 对象的修饰过的绝对路径 | 如果绝对路径的值为:d:/././test.txt,那么修饰过的绝对路径就为:d:/test.txt。 |
exists() | boolean | 判断 File 对象描述的文件是否真实存在 | |
isDirectory() | boolean | 判断 File 对象代表的文件是否是一个目录 | |
isFile() | boolean | 判断 File 对象代表的文件是否是一个普通文件 | |
createNewFile() | boolean | 根据 File 对象,自动创建一个空文件。成功创建后返回 true | 如果文件路径不正确或者没有权限,则可能创建失败。 |
delete() | boolean | 根据 File 对象,删除该文件。成功删除后返回 true | 如果文件路径不正确或者没有权限,则可能删除失败。 |
deleteOnExit() | void | 根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行 | |
list() | String[] | 返回 File 对象代表的目录下的所有文件名 | |
listFiles() | File[] | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 | |
mkdir() | boolean | 创建 File 对象代表的目录 | |
mkdirs() | boolean | 创建 File 对象代表的目录,如果必要,会创建中间目录 | |
renameTo(File dext) | boolean | 重命名文件或移动文件,当目录为空时也可以重命名目录 | |
canRead() | boolean | 判断用户是否对文件有可读权限 | |
canWrite() | boolean | 判断用户是否对文件有可写权限 |
2. 操作文件里的数据
文件内容的操作包括读文件和写文件,而对于这两种操作 Java 又提供了两种不同的类:
读类 | 写类 | 说明 |
---|---|---|
InputStream | OutputStream | 字节流,针对二进制文件进行读写,操作基本单位是字节 |
Reader | Writer | 字符流,针对文本文件进行读写,操作基本单位是字符 |
- 字节流: 它处理单元为1个字节,操作字节和字节数组,存储的是二进制文件,如果是音频文件、图片、歌曲,就用字节流。
- 字符流: 它处理的单元为2个字节的 Unicode 字符,分别操作字符、字符数组或字符串,字符流是由 Java 虚拟机将字节转化为2个字节的 Unicode 字符为单位的字符而成的,如果是关系到中文(文本)的,用字符流更好。
- 所有文件都是以字节的形式储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列。
- 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串。
- 字节流提供了处理任何类型的 IO 操作的功能,但它不能直接处理 Unicode 字符,而字符流就可以。
- 字节流在操作的时候本身不会用到缓冲区的,是与文件本身直接操作的;而字符流在操作的时候会使用到缓冲区的。
- 其中 InputStream/OutputStream 和 Reader/Writer 都实现了 Closeable 接口,所以可以不主动通过 close 方法去关闭该资源,而是通过代码可读性更高的 try-with-resource 操作在 try 中的内容结束后,无论是否有异常都关闭该资源。
- 使用 OutputStream 或 writer 打开文件默认会清空之前的文件内容
2.1 操作字节流数据
2.1.1 InputStream
InputStream 是一个抽象类,使用时需要使用具体的实现类。InputStream 的实现类很多,针对不同的输入设备都可以对应一个实现类,其中针对文件读取的实现类是 FileInputStream。
FileInputStream 构造方法:
构造方法 | 说明 |
---|---|
FileInputStream(File file) | 利用 File 构造对应文件输入流 |
FileInputStream(String name) | 利用文件路径构造对应文件输入流 |
InputStream 核心方法:
方法 | 返回值类型 | 说明 |
---|---|---|
read() | int | 一次读取一个字节的数据,如果返回 -1 表示文件读完了 |
read(byte[] b) | int | 一次最多读取 b.length 字节的数据到 b 中,返回值为实际读到的字节数量,如果返回 -1 表示文件读完了 |
read(byte[] b, int off, int len) | int | 一次最多读取 len 个字节到 b 中,并从 off 的位置开始存放,返回值为实际读到的字节数量,如果返回 -1 表示文件读完了 |
close() | void | 关闭字节流 |
为什么 read 方法的返回值是 Int 类型?
对于 read 方法的返回值,当读取的是数字和英文时,返回值是对应的 ascii 码;当读取的是汉字时,返回的是汉字的机内码,比如使用的是 GBK 编码方式,返回的就是 GBK 的内部编码。read 方法每次从 inputstream 中读取一个字节,而一个字节是8位,但当最高位是1的时候,二进制对应的 ascii 码值就是复数,而 ascii 是没有负数的,所以用 byte 类型表示不了。并且 11111111 对应的十进制值是 -1,而返回 -1 表示文件读取完毕了,则后面的数据就不会读了,因此 byte 类型不适合,int 类型则可以解决这个问题。
示例代码: 使用 read()
方法读取文件内容
public class Demo1
public static void main(String[] args) throws IOException
File file = new File("./test.txt");
StringBuilder sb = new StringBuilder();
try (InputStream inputStream = new FileInputStream(file))
while(true)
int b = inputStream.read();
if(b == -1)
break;
sb.append((char) b);
catch (IOException e)
e.printStackTrace();
System.out.println(sb.toString());
示例代码: 使用 read(byte[] b)
方法读取文件内容
public class Demo1
public static void main(String[] args) throws IOException
File file = new File("./test.txt");
byte[] buffer = new byte[1024];
try (InputStream inputStream = new FileInputStream(file))
while(true)
int len = inputStream.read(buffer);
if(len == -1)
break;
String s = new String(buffer, 0, len, "utf-8");
System.out.println(s);
catch (IOException e)
e.printStackTrace();
2.1.2 OutputStream
OutputStream 是一个抽象类,使用时需要使用具体的实现类。OutputStream 的实现类很多,针对不同的输出设备都可以对应一个实现类,其中针对文件读取的实现类是 FileOutputStream。
FileOutputStream 构造方法:
构造方法 | 说明 |
---|---|
FileOutputStream(File file) | 利用 File 构造对应文件输出流 |
FileOutputStream(String name) | 利用文件路径构造对应文件输出流 |
FileOutputStream(File file, boolean append) | append 表示是否追加数据到文件的末尾,为 true 表示追加,为 false 表示情空之前的内容重新加入 |
FileOutputStream(String name, boolean append) | append 表示是否追加数据到文件的末尾,为 true 表示追加,为 false 表示情空之前的内容重新加入 |
OutputStream 核心方法:
方法 | 返回值类型 | 说明 |
---|---|---|
write() | int | 一次写入一个字节的数据 |
write(byte[] b) | int | 一次最多写入 b.length 字节的数据到 b 中,返回值为实际写入的字节数量 |
write(byte[] b, int off, int len) | int | 一次最多写入 len 个字节到 b 中,并从 off 的位置开始存放,返回值为实际写入到的字节数量 |
close() | void | 关闭字节流 |
示例代码:
public class Demo1
public static void main(String[] args) throws IOException
File in = new File("./in.txt");
File out = new File("./out.txt");
byte[] buffer = new byte[1024];
try (InputStream inputStream = new FileInputStream(in);
OutputStream outputStream = new FileOutputStream(out))
while (true)
int len = inputStream.read(buffer);
if (len == -1)
break;
outputStream.write(buffer, 0, len);
catch (IOException e)
e.printStackTrace();
2.1.3 BufferedInputStream
BufferedInputStream 也是 InputStream 的具体实现类,相比于 FileInputStream 优化了系统调用,即通俗解释为:将数据保存了缓存区,但是减少磁盘 IO 并不是 BufferedInputStream 来做的,而是 OS 来做的。OS 根据局部性原理,会预读部分的数据到内存缓存区,这样下次 IO 如果读取数据在缓存命中了,就不需要等待磁盘的寻址,而是直接返回数据,效率就会快很多。
2.1.4 BufferedOutputStream
BufferedOutPutStream 也是 OutputStream 的具体实现类,相比于 FileOutputStream 优化了系统调优,即每次写数据的时候,都会将数据放入缓存区中,等缓存区满了之后,才会一次性写入到磁盘中,大大提高了效率。
2.2 操作字符流数据
2.2.1 Reader
Reader 是实现字符输入流的一种类型,其本身属于一个抽象类,使用时需要使用具体的实现类。Reader 的实现类很多,针对不同的输入设备都可以对应一个实现类,其中针对文件读取的实现类是 FileReader。Reader 的使用方式和 InputStream 相仿。
示例代码:
public class Demo2
public static void main(String[] args) throws FileNotFoundException
File file = new File("./test.txt");
StringBuilder sb = new StringBuilder();
try (Reader reader = new FileReader(file))
while (true)
int read = reader.read();
if (read == -1)
break;
sb.append((char) read);
catch (IOException e)
e.printStackTrace();
System.out.println(sb.toString());
2.2.2 Writer
Writer 是实现字符输出流的一种类型,其本身属于一个抽象类,使用时需要使用具体的实现类。Writer 的实现类很多,针对不同的输出设备都可以对应一个实现类,其中针对文件读取的实现类是 FileWriter。Writer 的使用方式和 OutputStream 相仿。
FileWriter 构造方法:
构造方法 | 说明 |
---|---|
FileWriter(File file) | 利用 File 构造对应文件输出流 |
FileWriter(String name) | 利用文件路径构造对应文件输出流 |
FileWriter(File file, boolean append) | append 表示是否追加数据到文件的末尾,为 true 表示追加,为 false 表示情空之前的内容重新加入 |
FileWriter(String name, boolean append) | append 表示是否追加数据到文件的末尾,为 true 表示追加,为 false 表示情空之前的内容重新加入 |
示例代码:
public class Demo2
public static void main(String[] args) throws FileNotFoundException
File in = new File("./in.txt");
File out = new File("./out.txt");
try (Reader reader = new FileReader(in);
Writer writer = new FileWriter(out))
while (true)
int read = reader.read();
if (read == -1)
break;
writer.write(read);
catch (IOException e)
e.printStackTrace();
2.2.3 BufferedReader
BufferedReader 也是 Reader 的具体实现类,相比于 Reader 优化了系统调用,即通俗解释为:将数据保存了缓存区,但是减少磁盘 IO 并不是 BufferedReader 来做的,而是 OS 来做的。OS 根据局部性原理,会预读部分的数据到内存缓存区,这样下次 IO 如果读取数据在缓存命中了,就不需要等待磁盘的寻址,而是直接返回数据,效率就会快很多。
2.2.4 BufferedWriter
BufferedWriter 也是 Writer 的具体实现类,相比于 Writer 优化了系统调优,即每次写数据的时候,都会将数据放入缓存区中,等缓存区满了之后,才会一次性写入到磁盘中,大大提高了效率。
2.3 Scanner 和 PrintWriter
Java 标准库中提供的 Scanner 和 PrintWriter 类能够像文件中读取文本数据和写入文本数据。
2.3.1 Scanner
java.util.Scanner 类常用来从控制台中读取字符串和基本类型的数值。Scanner 可以将输入的值以空白字符分割标记。
Scanner 的构造方法:
构造方法 | 说明 |
---|---|
Scanner(Readable source) | 创建一个 Scanner,从指定的可读资源中扫描标记,包括文件、文件路径、字符串等。 |
Scanner(InputStream source) | 创建一个 Scanner,从指定的字节输入流中扫把标记。 |
Scanner 常用方法:
方法 | 返回值类型 | 说明 |
---|---|---|
hasNext() | boolean | 如果 Scanner 还要更多的数据可读取,则返回 true |
next() | String | 从 Scanner 中读取下一个标记作为字符串返回 |
nextLine() | String | 从 Scanner 中读取一行,以换行符结束 |
close() | void | 关闭 Scanner |
System.in
为系统自带的标准输入流,该流是一直打开并准备提供输入数据。通常,这个流对应于键盘输入或由主机环境或用户指定的另一个输入源。- 使用 Scanner 没有必要关闭输入文件,但是关闭能够释放文件占有的资源。
示例代码:
public class Demo3
public static void main(String[] args)
try (Scanner scanner = new Scanner(new File("./test.txt")))
while (scanner.hasNext())
String s = scanner.next();
System.out.println(s);
catch (IOException e)
e.printStackTrace();
2.3.2 PrintWriter
java.io.PrintWriter 类可用来创建一个文件并向文本文件中写入数据。通常使用 System.out.println
向控制台输入文本。
PrintWriter 构造方法:
构造方法 | 说明 |
---|---|
PrintWriter(Writer out) | 为指定的字符输入流创建一个 PrintWriter。 |
PrintWriter(Writer out, boolean autoFlush) | 为指定的字符输入流创建一个 PrintWriter,如果 autoFlush 为 true,则 println、printf 或 format 方法将刷新输出缓冲区。 |
PrintWriter(OutputStream out) | 为指定的字节输入流创建一个 PrintWriter。 |
PrintWriter(OutputStream out, boolean autoFlush) | 为指定的字节输入流创建一个 PrintWriter,如果 autoFlush 为 true,则 println、printf 或 format 方法将刷新输出缓冲区。 |
PrintWriter(String fileName) | 为指定的文件路径创建一个 PrintWriter |
PrintWriter(String fileName, String csn) | 为指定的文件路径创建一个 PrintWriter,并且通过指定的字符集对字符进行编码。 |
PrintWriter(File file) | 为指定的文件对象创建一个 PrintWriter。 |
PrintWriter(File file, String scn) | 为指定的文件对象创建一个 PrintWriter,并且通过指定的字符集对字符进行编码。 |
PrintWriter 常用方法:
方法 | 返回值类型 | 说明 |
---|---|---|
print(String s) | void | 将字符串写入文件中 |
println(String s) | void | 将字符串写入文件中,多打印一个换行 |
printf(String s) | void | 将字符串写入文件中,按照指定格式写文件中 |
System.out
为系统自带的 printStream,表示控制台的标准 Java 对象,通过它能够向控制台输入数据。- 使用 PrintWriter 必须使用 close 方法关闭文件,或者使用 try-with-resources 自动关闭资源,狗则数据就不能正确地保存在文件中。
示例代码:
public class Demo3
public static void main(String[] args)
try (Scanner scanner = new Scanner(new File("./in.txt"));
PrintWriter printWriter = new PrintWriter("./out.txt"))
while (scanner.hasNext())
String s = scanner.next();
printWriter.println(s);
catch (IOException e)
e.printStackTrace();
以上是关于Java 基础语法Java 的文件操作的主要内容,如果未能解决你的问题,请参考以下文章