Java 文件I/O使用笔记

Java 文件I/O使用笔记

Java I/O的设计十分的繁杂,几乎每次使用起来都需要百度一下,很浪费时间。因此,本文希望尽可能少的列出足以满足平时文件I/O需求的知识点,以此来简化Java I/O的使用和记忆难度。


1. Text I/O & Binary I/O

关于Text I/O和Binary I/O的区别,引用《Introduction to Java Programming》中的一段话,这段话对这两者的区别做了很好的阐述:

  Computers do not differentiate between binary files and text files. All files are stored in binary format, and thus all files are essentially binary files. Text I/O is built upon binary I/O to provide a level of abstraction for character encoding and decoding, as shown in Figure 17.2a. Encoding and decoding are automatically performed for text I/O. The JVM converts Unicode to a file-specific encoding when writing a character, and it converts a file-specific encoding to Unicode when reading a character. For example, suppose you write the string “199” using text I/O to a file, each character is written to the file. Since the Unicode for character 1 is 0x0031, the Unicode 0x0031 is converted to a code that depends on the encoding scheme for the file. (Note that the prefix 0x denotes a hex number.) In the United States, the default encoding for text files on Windows is ASCII. The ASCII code for character 1 is 49 (0x31 in hex) and for character 9 is 57 (0x39 in hex). Thus, to write the characters 199, three bytes—0x31, 0x39, and 0x39—are sent to the output, as shown in Figure 17.2a.
  Binary I/O does not require conversions. If you write a numeric value to a file using binary I/O, the exact value in the memory is copied into the file. For example, a byte-type value 199 is represented as 0xC7 (199 = 12 * 161 + 7) in the memory and appears exactly as 0xC7 in the file, as shown in Figure 17.2b. When you read a byte using binary I/O, one byte value is read from the input.
  In general, you should use text input to read a file created by a text editor or a text output program, and use binary input to read a file created by a Java binary output program.
  Binary I/O is more efficient than text I/O, because binary I/O does not require encoding and decoding. Binary files are independent of the encoding scheme on the host machine and thus are portable. Java programs on any machine can read a binary file created by a Java program. This is why Java class files are binary files. Java class files can run on a JVM on any machine.
在这里插入图片描述

概括来说,如果你需要读入/写出人可读的文件,那么就选择Text I/O,如果只是要起到记录数据的作用,那么就选择Binary I/O,因为Binary I/O没有编码/解码的过程,所以速度更快。

2. Binary I/O

这是我们平时用的比较多的一种I/O,完整的InputStream/OutputStream家族有兴趣的话可以自行查资料,这里只列出我们日常使用过程中需要记忆的一部分:
在这里插入图片描述

  • FileInputStream/FIleOutputStream:提供了基本的文件读入/写出功能,只能以byte(s)为单位进行。
  • BufferedInputStream/BufferedOutputStream:和FileInputStream/FIleOutputStream类似,只是增加了buffer,能有效提高读入/写出的速度。
  • DataInputStream/DataOutputStream:在基本的byte(s)的基础上,多加了一层,根据需求完成了多个bytes组合和一个java的内置类型(比如int,long,char,Boolean等)或者string之间的转换,当想要读入/写出java基本数据类型或者string时可以使用。
  • ObjectInputStream/ObjectOutputStream:和DataInputStream/DataOutputStream类似,也是实现了基本的bytes和java对象之间的转换,只不过他们不只局限于基本数据类型和string,还包括了所有实现了Serializable接口的java对象!

所以,我们通常的使用思路就是在基础的bytes的stream上加上buffer,如果有需求再包上Data或者Object,就好啦,示例如下:

			DataInputStream dataInputStream = new DataInputStream(
                                                 new BufferedInputStream(
                                                      new FileInputStream("filePath")));

3. Text I/O

这个就是Reader/Writer家族啦!完整的家族成员有兴趣也可以自行查资料。通常选择Text I/O是因为我们想要读入一些人可读的文件或者输出一些人可读的数据到文件中保存起来。这里我们需要记住的也非常少:
在这里插入图片描述

  • InputStreamReader/OutputStreamWriter:实现了从Binary I/O的InputStream/OutputStream向Text I/O的Reader/Writer的转换。实际也就是对Binary I/O加上了编码/解码的过程。
  • FileReader/FileWriter:和 FileInputStream/FIleOutputStream类似,提供了基本的读入/写出功能,以char(s)为单位。
  • BufferedReader/BufferedWriter: 和BufferedInputStream/BufferedOutputStream类似,提供buffer,加快读入/写出的速度。
  • PrintWriter:和DataOutputStream/ObjectOutputStream类似,多加了一层转换层,提供了写出int,long等数据类型的功能。同时,PrintWriter自带buffer,可以通过设置autoFlush为true来禁用buffer。
  • Reader中并没有与PrintWriter对应的XXXReader,如果想要从可读的文件中读出int,Boolean等时,可以根据文件内容的具体格式,一行一行的读入再逐行解析出这行包括的数据或者采用Scanner。比如读入“1 2 3”,然后通过处理字符串得到三个整数1,2,3;或者通过三次scanner.nextInt()得到。(注:Scanner并不属于Reader/Writer家族)

下面是一些使用示例:

			//将OutputStream包成Writer
			FileOutputStream fileOutputStream = new FileOutputStream("filePath");
			OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
			BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter) ;//再包上一层buffer
			
			BufferedReader bufferedReader = new BufferedReader(
                                                new FileReader("filePath"));

			PrintWriter writer = new PrintWriter("filePath");
			
			//使用Scanner处理文件读入
			Scanner scanner = new Scanner(new File("filePath"));

4. 结语

本文所列出的这些知识仅能满足平时写些小项目时的文件I/O需求,对于其他的复杂情况,还需要在实践中学习积累,只有这样,才能熟练掌握Java I/O。

5. 附录

这里记录的是一些我在看Java相关的书籍时发现的对理解/使用java I/O有帮助的句子。

  • The most important reason for the Reader and Writer hierarchies is for internationalization. The old I/O stream hierarchy supports only 8-bit byte streams and doesn’t handle the 16-bit Unicode characters well. Since Unicode is used for internationalization (and Java’s native char is 16-bit Unicode), the Reader and Writer hierarchies were added to support Unicode in all I/O operations.
  • There’s one direction that’s quite clear: Whenever you want to use readLine( ), you shouldn’t do it with a DataInputStream (this is met with a deprecation message at compile time), but instead use a BufferedReader. Other than this, DataInputStream is still a “preferred” member of the I/O library.
  • When you are using a DataOutputStream, the only reliable way to write a String so that it can be recovered by a DataInputStream is to use UTF-8 encoding( writeUTF( ) and readUTF( ) ).
  • A PrintWriter formats data so that it’s readable by a human. However, to output data for recovery by another stream, you use a DataOutputStream to write the data and a DataInputStream to recover the data.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值