目录
Java字节流(Byte Stream)
FileInputStream和FileOutputStream
Java字符流(Character Stream)
FileReader和FileWriter
如何在使用是区分什么时候用输出什么时候用输入
Write方法
close方法
Java中的close方法本身抛出的异常是什么
FileOutputStream(文件输出流)
FileInputStream(文件输入流)
FileInputStream文件输入流,参数中的文件不存在时会直接抛出异常不会尝试创建新文件;
read方法和Write方法
Java中的流(stream)是数据传输的一种方式,可以将输入或输出数据从一个地方传递到另一个地方。Java的I/O库提供了两种类型的流:字节流和字符流。
Java字节流(Byte Stream)
Java字节流以字节为单位进行读写操作,是处理所有类型的二进制数据的推荐方式。它们在I/O基础设施中使用最广泛,因为它们处理原始的二进制数据。
FileInputStream和FileOutputStream
Java中最基本的字节流类是FileInputStream和FileOutputStream。文件输入流(FileInputStream)用于从文件中读取数据,而文件输出流(FileOutputStream)用于向文件中写入数据。这两个类可以用来移动二进制数据,比如图像和声音等。
-
优点
- 字节流对于任何类型的文件都可以使用,包括文本和二进制文件。
- 字节流通常比字符流更快,在处理大量数据时性能更好。
-
缺点
- 不适合处理文本数据,可能会导致编码问题。
- 在处理文本文件时需要手动进行编解码。
-
使用案例
- 图片和视频的读写操作
- 数据压缩和加密
Java字符流(Character Stream)
Java字符流以字符为单位进行读写操作,是处理文本数据的首选方式。它们使用Unicode编码并在内存中使用16位字符集表示。
FileReader和FileWriter
Java中最基本的字符流类是FileReader和FileWriter。文件读取器(FileReader)用于从文本文件中读取数据,而文件写入器(FileWriter)用于向文本文件中写入数据。
-
优点
- 处理文本文件时,字符流通常比字节流更方便。
- 自动进行编解码,无需手动进行转换。
-
缺点
- 在处理二进制数据时不如字节流效率高。
- 不能处理所有类型的文件,比如图片或视频等。
-
使用案例
- 文本文件的读写操作
- 网络传输中的文本数据的读写操作
总的来说,字节流适合处理任何类型的文件,但在处理文本数据时需要手动进行编解码。字符流适合处理文本文件,并且自动进行编解码。因此,根据具体的使用场景和需求选择合适的流非常重要。
如何在使用是区分什么时候用输出什么时候用输入
这个问题困扰我很长时间啊,关键时刻就会搞混,为此痛书下文:(以文件的读写流举例)
FileInputStream:文件输入流,从文件中读出数据,方法read();
FileOutputStream:文件输出流,向文件中写入数据,方法write();
记住以上两句话,不要去问为什么,记住就好了,等你彻底记住了在问为什么;
Write方法
这里为什么把这个方法单独拿出来呢?因为这个方法本身会抛出受检异常,你必须在编译之前对他做出处理;
在Java中,write()
方法用于将数据写入输出流。这个方法本身可能会抛出多种异常,包括以下几种:
-
IOException
- 描述:当发生I/O错误(如文件系统错误或网络错误)时抛出。
-
NullPointerException
- 描述:当参数为null时抛出。
-
IndexOutOfBoundsException
- 描述:当指定的偏移量和长度超出了有效数据范围时抛出。
需要注意的是,如果使用带缓冲区的流对象(例如BufferedOutputStream
),则调用write()
方法不一定会触发I/O操作。相反,它会将数据存储在缓冲区中,并且只有当缓冲区已满或手动刷新缓冲区时才会执行实际的I/O操作。在这种情况下,如果发生I/O错误,则可能会在刷新缓冲区时抛出异常,而不是在调用write()
方法时抛出异常。
close方法
为了加深联想记忆,我们在单独把close方法拿出来,同样它本身也会抛出异常,我之前一直以为他的异常只是null异常(就是流对象值为null时,仍旧调用close时才抛出异常),但实则不然,以下代码为例(注意下面代码有错误):
if(fin!=null){fin.close();}
因为我单独写出 fin.close()时会报异常,所以我在fin.close()外面加入了if判断,之后他仍旧会抛出异常,之后我就发觉不对,重新查了下资料得:
Java中的close方法本身抛出的异常是什么
在Java中,close()
方法是用于关闭流的方法。当调用close()
方法时,可能会发生异常并抛出异常。具体来说,close()
方法本身可能会抛出IOException
异常。
IOException
是Java中的一个checked exception(受检异常),表示在输入/输出过程中发生了一般性错误。因为close()
方法涉及到I/O操作,所以它可能会在关闭流的过程中抛出IOException
异常。例如,在使用文件输入/输出流时,如果在关闭流之前尚未完成读取/写入操作,则可能会出现IOException
异常。同样,在使用网络套接字时,如果在从套接字中读取或写入数据时发生错误,则可能在关闭套接字之前出现IOException
异常。
因此,当使用close()
方法时,需要使用try-catch语句来捕获可能抛出的IOException
异常,并进行适当的异常处理。通常情况下,在finally块中调用close()
方法是良好的编程习惯,以确保资源得以正确释放。例如:
FileInputStream in = null;
try {in = new FileInputStream("example.txt");// ...
} catch (IOException e) {// 处理异常
} finally {if (in != null) {try {in.close();} catch (IOException e) {// 处理异常}}
}
FileOutputStream(文件输出流)
然后我们来谈一谈FileOutputStream,这个流对象很牛逼啊,有些不为人知的操作:
在Java中,FileOutputStream
有两种构造函数来创建一个文件输出流对象,这两个构造函数的参数如下:
-
FileOutputStream(File file)
- 参数类型:
File
- 描述:创建一个将数据写入指定文件的文件输出流对象。如果指定的文件不存在,则会尝试创建该文件。
- 参数类型:
-
FileOutputStream(String name, boolean append)
- 参数类型:
String name
: 文件名(包括其路径)。boolean append
: 如果为true,则此文件输出流将被打开以进行追加写入;否则文件将被覆盖。
- 描述:创建一个将数据写入指定文件的文件输出流对象。如果指定的文件不存在,并且
append
参数为false,则会尝试创建该文件。
- 参数类型:
需要注意的是,如果使用第二种构造函数来创建FileOutputStream
对象,还可以使用另一种重载形式的构造函数来设置缓冲区大小。例如:
FileOutputStream fos = new FileOutputStream("example.txt", true);
BufferedOutputStream bos = new BufferedOutputStream(fos, 4096);
上述代码中,BufferedOutputStream
的构造函数接收一个FileOutputStream
对象和一个整数参数作为输入。该整数表示缓冲区的大小。通过使用带有缓冲区大小参数的构造函数,可以提高输出性能并减少系统调用次数
FileInputStream(文件输入流)
相对于输出流,输入流比较简单:在Java中,FileInputStream
有三个构造函数用于创建一个文件输入流对象,这三个构造函数的参数如下:
-
FileInputStream(File file)
- 参数类型:
File
- 描述:创建一个从指定文件读取数据的文件输入流对象。
- 参数类型:
-
FileInputStream(String name)
- 参数类型:
String
- 描述:创建一个从指定路径名(包括文件名)读取数据的文件输入流对象。
- 参数类型:
-
FileInputStream(FileDescriptor fdObj)
- 参数类型:
FileDescriptor
- 描述:创建一个从指定文件描述符读取数据的文件输入流对象。
- 参数类型:
需要注意的是,FileInputStream
类没有设置缓冲区的构造函数。如果需要使用带有缓冲区的输入流对象,则可以将FileInputStream
与BufferedInputStream
一起使用。例如:
FileInputStream fis = new FileInputStream("example.txt");
BufferedInputStream bis = new BufferedInputStream(fis, 4096);
上述代码中,BufferedInputStream
构造函数接收一个FileInputStream
对象和一个整数参数作为输入。该整数表示缓冲区的大小。通过使用带有缓冲区大小参数的构造函数,可以提高输入性能并减少系统调用次数。
FileInputStream文件输入流,参数中的文件不存在时会直接抛出异常不会尝试创建新文件;
在Java中,FileInputStream
的构造函数用于创建一个从文件读取数据的输入流对象。如果指定的文件不存在,则会抛出FileNotFoundException
异常,而不是尝试创建该文件。
因此,如果要使用FileInputStream
从文件读取数据,并且不确定文件是否存在,可以通过以下步骤来避免出现异常:
- 使用Java中的
File
类或其他文件操作API来检查文件是否存在。 - 如果文件存在,则使用
FileInputStream
构造函数来创建输入流对象;否则,进行相应的错误处理。
例如,下面的代码演示了如何检查文件是否存在并使用FileInputStream
从文件读取数据:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class FileInputStreamExample {public static void main(String[] args) {File file = new File("example.txt");if (file.exists()) {try {FileInputStream fis = new FileInputStream(file);// 从输入流中读取数据...fis.close();} catch (IOException e) {e.printStackTrace();}} else {System.err.println("File not found: " + file.getAbsolutePath());}}}
上述代码中,首先检查文件是否存在,如果存在则使用FileInputStream
构造函数创建输入流对象并从中读取数据。如果文件不存在,则输出错误信息并终止程序。
需要注意的是,FileInputStream
只能用于读取已存在的文件,并不能用于创建新的文件。如果需要创建新的文件,应该使用FileOutputStream
(或其他文件操作API)来创建输出流并写入数据。
read方法和Write方法
这个部分里面我们主要强调的是,read和write方法的参数以及返回值,你可以从下图中看出,
-
返回值:
int
:返回实际读取的字节数。如果已经到达文件的末尾,则返回-1。在实际应用中我们通过返回的值来判断是否读取完数据;
- 参数
- 空参表示一次读出一个字节数据,然后其他上面都有;
对于Write方法,他没有返回值,主要是参数,可以一次写入一个字节,或者一个字节数组的数据;
fou = new FileOutputStream("./2.txt");fin = new FileInputStream("");String str = new String("qwertyuiop");fou.write(2);//write方法本身会抛出异常;一次写入一个字节fou.write(str.getBytes());//一次写入一个字节数组