【Java|基础篇】File类和IO流

简介: .File类File类是Java中用于表示文件或目录的类。它提供了一些方法来操作文件和目录的属性和内容,可以进行文件的创建、删除、重命名等操作。

1.File类

File类是Java中用于表示文件或目录的类。它提供了一些方法来操作文件和目录的属性和内容,可以进行文件的创建、删除、重命名等操作。


File类可以用于表示磁盘上的实际文件或目录,也可以表示一个虚拟的文件或目录。File对象可以通过路径来创建,路径可以是绝对路径或相对路径。


绝对路径(Absolute Path):绝对路径是从文件系统的根目录开始描述文件或目录的位置。它包含了完整的路径信息,从根目录一直到目标文件或目录的全路径。在Windows中,绝对路径以盘符(例如C:\)开头;在Unix/Linux系统中,绝对路径以斜杠(/)开头。


相对路径(Relative Path):相对路径是相对于当前工作目录或引用文件所在位置的路径。它指定文件或目录相对于当前位置的位置关系。相对路径没有从根目录开始的完整路径,而是通过使用“.”(当前目录)和“…”(上级目录)等符号来描述位置关系。


创建File类对象:

File file = new File("文件路径(绝对/相对)");
// 此处的文件路径不要要求一定存在

File类中的常用方法:

方法

描述

getParent()

获取文件的父目录

getName()

获取文件的名字

getPath()

获取文件的路径

getAbsolutePath()

获取绝对路径

getCanonicalPath()

获取标准的绝地路径。

createNewFile()

创建文件

exists()

判断文件是否存在

delete()

删除文件

mkdir()

创建目录(与src同一级)

mkdirs()

创建多级目录

isDirectory()

判断是否为目录

isFile()

是否为文件

renameTo(File dest)

重命名

list()

返回当前目录下所有文件名

上述都是一些获取文件和目录的信息以及增删等操作. 接下来介绍一些文件的读写操作.


2.流的概念

在Java的IO操作中,流(Stream)是指数据的传输管道。它将程序与输入/输出设备(例如文件、网络连接等)连接起来,使得数据能够在程序和设备之间流动。


Java的IO流分为输入流和输出流两种类型。


输入流用于从外部读取数据

输出流用于向外部写入数据。

Java中的流操作按照字节或字符的方式进行。字节流(byte stream)是以字节为单位进行数据传输的,适用于处理二进制数据。字符流(character stream)是以字符为单位进行数据传输的,适用于处理文本数据。

1ae5248d1c584581bb951f42a14cfa85.png



这里的InputStream,OutputStream,Reader和Writer都是抽象类.Java提供了一些实现这些抽象父类的子类,用于应对不同的场景.


3.InputStream

InputStream的子类可以根据不同的数据源提供不同的实现,例如FileInputStream用于从文件中读取数据,ByteArrayInputStream用于从字节数组中读取数据,SocketInputStream用于从网络连接中读取数据等。

对于InputStream,主要讲解FileInputStream

   public static void main(String[] args) throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("文件路径");
        inputStream.close();
    }

在创建实例时,要传入一个文件路径.这里需要处理一个异常FileNotFoundException(文件没找到).


读文件需要先打开文件,打开才能读,读完之后要关闭文件(close)


InputStream类的常用方法为read()和close()方法


close()方法:关闭输入流,释放与之关联的资源。


而read()方法有三个版本:


080e9310d73f4041a932dab636402300.png


int read():从输入流中读取数据的下一个字节,并返回读取到的字节值。如果已经到达流的末尾,则返回-1。

int read(byte[] b):从输入流中最多读取b.length个字节,并将其存储在字节数组b中。返回实际读取的字节数量。如果已经到达流的末尾,则返回-1。

int read(byte b[], int off, int len): 从输入流中读取最多len个字节,并将其存储在从偏移量off开始的字节数组b中。

4.OutputStream

OutputStream的子类可以根据不同的目的地提供不同的实现,例如FileOutputStream用于向文件中写入数据,ByteArrayOutputStream用于向字节数组中写入数据,SocketOutputStream用于向网络连接中写入数据等。

对于OutputStream,主要讲解FileOutputStream
    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("文件路径");
        outputStream.close();
    }


close()方法: 关闭输出流,释放资源.


OutputStream中的一个常用方法: write():


1aa42ffe542541469b9ce8d91df81b10.png


这里有三个重载的版本


write(int b):写入一个字节到输出流中。b是一个整数,表示要写入的字节的值(范围是0~255)。

write(byte[] b):将整个字节数组b写入输出流中。

write(byte[] b, int off, int len):将字节数组b中从偏移量off开始的len个字节写入输出流中。

注意:使用OutputStream写文件时,只要文件打开成功,就会把文件原有的内容清空.


5.Reader

Reader的子类可以根据不同的字符输入源提供不同的实现,例如FileReader用于从文件中读取字符数据,StringReader用于从字符串中读取字符数据,BufferedReader用于从字符缓冲区中读取字符数据等。


使用方式于InputStream类似,只不过Reader是以字符流的形式进行读文件

public static void main(String[] args) throws IOException {
     Reader reader = new FileReader("");
     reader.close();
}

020609ec444e4ee2a03d25d72152a9a1.png


read():读取单个字符,并返回其Unicode值。如果已到达流的末尾,则返回-1。

read(char[] cbuf):将字符读入到指定的字符数组cbuf中,并返回读取的字符数。

read(char[] cbuf, int off, int len):将字符读入到指定的字符数组cbuf中,从偏移量off开始,最多读取len个字符,并返回实际读取的字符数。

read(CharBuffer target):将字符读入到指定的CharBuffer对象中,并返回读取的字符数。

6.Writer

Writer是用于向字符输出流中写入字符数据。


Writer的子类可以根据不同的字符输出目的地提供不同的实现,例如FileWriter用于向文件中写入字符数据,StringWriter用于向字符串中写入字符数据,BufferedWriter用于向字符缓冲区中写入字符数据等。


d8226358d9c04ff18de7961d463ed786.png


write(int c):将指定的字符写入输出流中。

write(String str):将字符串写入输出流中。

write(char[] cbuf):将字符数组中的字符写入输出流中。

write(String str, int off, int len):将字符串中从偏移量off开始的len个字符写入输出流中。

write(char[] cbuf, int off, int len):将字符数组中从偏移量off开始的len个字符写入输出流中。

7.使用Scanner读文件

追对于文本文件,也可以使用Scanner进行读取


例如这里有一个test.txt文件

0431ce84a48c465ab4e2430b98a98923.png


接下来介绍使用Scanner进行读文件

public class Demo5 {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("test.txt");
        Scanner scanner = new Scanner(inputStream);
        while (scanner.hasNext()){
            System.out.println(scanner.next());
        }
        inputStream.close();
    }
}


运行结果:

3ca2b8f02a7641adaa415f06c0c4e363.png


解释一下:InputStream是字节流,Scanner是在InputStream的基础上,包装出来的字符流.


8.使用PrintWriter写文件

与Scanner进行读文件类似,通过将FileOutputStream对象作为参数,创建了一个PrintWriter对象printWriter。


PrintWriter类提供了一系列的print和println方法,用于以友好的方式输出数据。这些方法可以接受不同类型的数据作为参数,并将其转换为字符串并写入输出流中。


例如,常用的方法包括:


print(boolean b) / println(boolean b):以字符串形式写入一个boolean值。

print(char c) / println(char c):以字符串形式写入一个字符。

print(int i) / println(int i):以字符串形式写入一个整数。

print(double d) / println(double d):以字符串形式写入一个双精度浮点数。

print(String s) / println(String s):写入一个字符串。

printf(String format, Object… args):使用指定的格式字符串和参数进行格式化输出。

需要注意的是,在使用完PrintWriter后,需要调用close()方法关闭流,以确保数据被正确地写入目的地并释放资源。


代码:


public class Demo6 {
    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("test.txt");
        PrintWriter printWriter = new PrintWriter(outputStream);
        printWriter.printf("hello PrintWriter");
        printWriter.close();
        outputStream.close();
    }
}


运行结果:


c53ad4fcd1a3413bb8c5456f05acca1b.png

9.close()方法

上述输入流和输出流的读文件和写文件后,都要进行close.是为什么呢?


原因是 每个进程都对应者PCB(可能是多个),PCB里有一个字段,文件描述符表(同一个进程里有多个PCB共同使用同一份文件描述符表),进程没打开一个文件,就会在文件描述表中创建一个项表示 一个文件.关闭文件意味着释放文件描述表中的项.如果不关闭文件,表项就在这里占着位置. 如果持续打开文件,不关闭,文件描述符表中的项就会被耗尽,从而导致后续打开文件失败. 这也称"文件资源泄漏"


为了避免上述问题,就需要保证close方法一定能被执行到.


因此就可以使用 try,finally保证close方法一定被执行到


 

public static void main(String[] args) throws IOException {
        Writer writer = null;
        try {
            writer = new FileWriter("文件路径");
            // do something
        } finally {
            writer.close();
        }
    }


除了上述这种写法,还有一种写法(try with resources)

public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("文件路径")) {
            // do something
        }
    }


当try中的代码执行结束,就会自动调用对应对象的close方法.而且()中可以放多个对象,对象之间用;进行分割


10.flush()方法

flush()方法是Java IO流中的一个方法,用于刷新缓冲区,并确保数据被写入到目的地。


缓冲区(Buffer)是用于临时存储数据的一块内存区域,它可以提高IO操作的效率。

在Java的IO流中,使用缓冲区可以减少单次IO操作的次数,从而提高读取和写入数据的效率。通常情况下,IO流会使用内部的缓冲区来存储数据,然后在一定条件下将缓冲区中的数据进行读取或写入。


在Java的输出流(OutputStream/Writer)中,flush()方法的作用是将缓冲区中的数据强制刷新到目的地。通常情况下,输出流会使用内部的缓冲区来提高写入效率,即将数据先写入到缓冲区中,然后再一次性写入到目的地。而flush()方法的调用可以让输出流立即将缓冲区的数据写入到目的地,而不是等到缓冲区满或流关闭时才写入。


注: 调用close()方法也会刷新缓冲区,并确保所有数据都被写入


11.总结

Java IO流主要涉及以下类:


InputStream和OutputStream:字节流的基类,用于读取和写入字节数据。

Reader和Writer:字符流的基类,用于读取和写入字符数据。

FileInputStream和FileOutputStream:用于从文件中读取和写入字节数据。

FileReader和FileWriter:用于从文件中读取和写入字符数据。

同时可以使用Scanner和PrintWriter简化开发,使用完流对象后,一定要记得调用close操作.

bca0142468be4910bf3f803eec1b82d4.gif


相关文章
|
1月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
151 57
|
5天前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
1月前
|
Java
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
52 9
|
1月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
54 8
|
1月前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
73 17
|
1月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
135 4
|
1月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
78 2
|
1月前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
58 4
|
1月前
|
Java 编译器 Maven
Java“class file contains wrong class”解决
当Java程序运行时出现“class file contains wrong class”错误,通常是因为类文件与预期的类名不匹配。解决方法包括:1. 确保类名和文件名一致;2. 清理并重新编译项目;3. 检查包声明是否正确。
64 3