Java 基础语法Java 的文件操作

Posted 吞吞吐吐大魔王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 基础语法Java 的文件操作相关的知识,希望对你有一定的参考价值。

文章目录


Java 操作文件包括了两个层面:

  • 在文件系统的层面上来操作文件,包括创建文件、删除文件、创建目录、拷贝文件等等。
  • 操作文件里保存的数据,包括读文件、写文件。

1. 在文件系统层面操作文件

1.1 File 类介绍

Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。不过有 File 对象,并不代表对应的文件真实存在。

1.2 File 常见属性

属性修饰符及类型说明
pathSeparatorstatic String依赖于系统的路径分隔符,String 类型的表示
pathSeparatorstatic 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 又提供了两种不同的类:

读类写类说明
InputStreamOutputStream字节流,针对二进制文件进行读写,操作基本单位是字节
ReaderWriter字符流,针对文本文件进行读写,操作基本单位是字符
  • 字节流: 它处理单元为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 的文件操作的主要内容,如果未能解决你的问题,请参考以下文章

Java 基础语法Java 的文件操作

java语法基础,具体内容

Java基础——接口

Java基础05 实施接口

22年最新Java笔记:Day1-Java基础语法(日更)

Scala 基础语法