我们对文件的概念已经非常熟悉了,比如常见的 Word 文档、txt 文件、源文件等。文件是数据源的一种,最主要的作用是保存数据。
在《 载入内存,让程序运行起来 》一文中我们提到,所有的文件(保存在磁盘)都要载入内存才能处理,所有的数据必须写入文件(磁盘)才不会丢失。数据在文件和内存之间传递的过程叫做 文件流 ,类似水从一个地方流动到另一个地方。数据从文件复制到内存的过程叫做 输入流 ,从内存保存到文件的过程叫做 输出流 。
图1:文件流示意图
文件是数据源的一种,除了文件,还有数据库、网络、键盘等;数据传递到内存也就是保存到 Java 程序的变量(例如字符串、数组、缓冲区等)。我们把数据在数据源和程序(内存)之间传递的过程叫做 数据流(Data Stream) 。相应的,数据从数据源到程序(内存)的过程叫做 输入流(Input Stream) ,从程序(内存)到数据源的过程叫做 输出流(Output Stream) 。
输入输出(Input output,IO)是指程序(内存)与外部设备(键盘、显示器、磁盘、其他计算机等)进行交互的操作。几乎所有的程序都有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等。通过输入和输出操作可以从外界接收信息,或者是把信息传递给外界。Java把这些输入与输出操作用流来实现,通过统一的接口来表示,从而使程序设计更为简单。
拿 BMP 文件举例,其头部的长度较为固定,前2字节用来记录文件为BMP格式,接下来的8个字节用来记录文件长度,再接下来的4字节用来记录 BMP 文件头的长度。
文本文件是基于字符编码的,常见的编码方式有 ASCII、UNICODE、UTF-8 等;指定编码方式后,每个字节(也可以是每两个、三个字节)所表示的字符是一样的,任何程序都可以正确读取。
二进制文件是自定义编码的,也就是说,你可以根据具体程序指定每个字节(或者每两个、三个字节)代表什么意思。例如,A 程序是图像编辑器,指定 01001111 代表红色,B 程序是视频播放器,它把 01001111 理解为快进,显然是不对的。
所以,字符文件是通用的,任何程序只要按照对应的编码方式打开都可以正确显示,二进制文件只有特定的程序才能处理。
字节流可以用来处理二进制文件和字符文件(即处理任何文件),字符流只能用来处理字符文件。
需要注意的是,为满足字符的国际化表示,Java语言的字符编码采用的是16位的Unicode码,而普通文本文件中采用的是8位ASCⅡ码。
java.io 包中的类比较繁杂,给初学者带来了一定的障碍,这或许是Java的“败笔”。不过,经常使用的类非常有限,IO 操作的流程也比较固定,本教程会从实际问题入手,重点讲解文件操作的步骤,让大家触类旁通。
下面列出了 java.io 包中的部分类,大家暂时不必理解,也不必记忆,后续我们会详细分析:
图2:Java.io 包(虚线框表示抽象类)
抛开File类和RandomAccessFile类,我们先来看剩下的四个类:
这四个类是所有IO类的父类,包含了一些通用的方法和属性,是我们讲解的重点;不过由于都是抽象类,不能直接实例化,所以实际开发中都是使用它们的子类。
另外,针对一些频繁的设备交互,Java 也预定了3个可以直接使用的流对象,不需要你再手动实例化,分别是:
当需要读取磁盘上的文件时,操作系统会开辟一个缓冲区(一块内存),把读出的数据先放在缓冲区,再从缓冲区中读取数据。这样,下次读取相同的数据时就不用“远征”到磁盘,可以直接从缓冲区中读取,提高IO速度。
反之也一样,向磁盘写入数据时也会开辟缓冲区,操作系统将数据发送到缓冲区,而不是直接发送到外部设备,当缓冲区满时,或者关闭程序时,再将缓冲区中的数据全部写入磁盘。写入缓存的速度远远大于写入磁盘的速度,CPU将数据写入缓存后就可以干别的事情了,不用等待写入磁盘。
缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
在Java输入输出操作中会经常使用缓冲区,大家一定要理解这个概念。
在《 载入内存,让程序运行起来 》一文中我们提到,所有的文件(保存在磁盘)都要载入内存才能处理,所有的数据必须写入文件(磁盘)才不会丢失。数据在文件和内存之间传递的过程叫做 文件流 ,类似水从一个地方流动到另一个地方。数据从文件复制到内存的过程叫做 输入流 ,从内存保存到文件的过程叫做 输出流 。
图1:文件流示意图
文件是数据源的一种,除了文件,还有数据库、网络、键盘等;数据传递到内存也就是保存到 Java 程序的变量(例如字符串、数组、缓冲区等)。我们把数据在数据源和程序(内存)之间传递的过程叫做 数据流(Data Stream) 。相应的,数据从数据源到程序(内存)的过程叫做 输入流(Input Stream) ,从程序(内存)到数据源的过程叫做 输出流(Output Stream) 。
输入输出(Input output,IO)是指程序(内存)与外部设备(键盘、显示器、磁盘、其他计算机等)进行交互的操作。几乎所有的程序都有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等。通过输入和输出操作可以从外界接收信息,或者是把信息传递给外界。Java把这些输入与输出操作用流来实现,通过统一的接口来表示,从而使程序设计更为简单。
二进制文件和字符文件(文本文件)
文件可以分为两类: 二进制文件 和 字符(文本)文件 。从物理上讲二进制文件和字符文件没有区别,都是以二进制的形式保存在磁盘上。但是它们在文件的组织形式上不一样,二进制文件有 文件头(File Header) ,用以表明文件的大小、类型等信息,程序在处理二进制文件时一般会先分析文件头,判断文件是否合法,也就是说,文件头后面的数据才是程序真正要处理的;字符文件没有文件头,第一个字节就是要显示的内容。拿 BMP 文件举例,其头部的长度较为固定,前2字节用来记录文件为BMP格式,接下来的8个字节用来记录文件长度,再接下来的4字节用来记录 BMP 文件头的长度。
文本文件是基于字符编码的,常见的编码方式有 ASCII、UNICODE、UTF-8 等;指定编码方式后,每个字节(也可以是每两个、三个字节)所表示的字符是一样的,任何程序都可以正确读取。
二进制文件是自定义编码的,也就是说,你可以根据具体程序指定每个字节(或者每两个、三个字节)代表什么意思。例如,A 程序是图像编辑器,指定 01001111 代表红色,B 程序是视频播放器,它把 01001111 理解为快进,显然是不对的。
所以,字符文件是通用的,任何程序只要按照对应的编码方式打开都可以正确显示,二进制文件只有特定的程序才能处理。
Java 流概述
Java 提供了 java.io 包来处理输入输出操作。java.io 包中的类可以分为两种类型:- 一是字节流,数据的处理以字节为基本单位,每次读写8位二进制数(一个字节)。也称为二进制流。
- 二是字符流,用于字符数据的处理,每次读写16位二进制数(两个字节)。
字节流可以用来处理二进制文件和字符文件(即处理任何文件),字符流只能用来处理字符文件。
需要注意的是,为满足字符的国际化表示,Java语言的字符编码采用的是16位的Unicode码,而普通文本文件中采用的是8位ASCⅡ码。
java.io 包中的类比较繁杂,给初学者带来了一定的障碍,这或许是Java的“败笔”。不过,经常使用的类非常有限,IO 操作的流程也比较固定,本教程会从实际问题入手,重点讲解文件操作的步骤,让大家触类旁通。
下面列出了 java.io 包中的部分类,大家暂时不必理解,也不必记忆,后续我们会详细分析:
图2:Java.io 包(虚线框表示抽象类)
抛开File类和RandomAccessFile类,我们先来看剩下的四个类:
| 字节流 | 字符流 | |
|---|---|---|
| 输入 | InputStream | Reader |
| 输出 | OutputStream | Writer |
这四个类是所有IO类的父类,包含了一些通用的方法和属性,是我们讲解的重点;不过由于都是抽象类,不能直接实例化,所以实际开发中都是使用它们的子类。
另外,针对一些频繁的设备交互,Java 也预定了3个可以直接使用的流对象,不需要你再手动实例化,分别是:
- System.in(标准输入),通常代表键盘输入。
- System.out(标准输出):通常写往显示器。
- System.err(标准错误输出):通常写往显示器。
缓冲区
缓冲区又称为缓存,它是内存空间的一部分。当需要读取磁盘上的文件时,操作系统会开辟一个缓冲区(一块内存),把读出的数据先放在缓冲区,再从缓冲区中读取数据。这样,下次读取相同的数据时就不用“远征”到磁盘,可以直接从缓冲区中读取,提高IO速度。
反之也一样,向磁盘写入数据时也会开辟缓冲区,操作系统将数据发送到缓冲区,而不是直接发送到外部设备,当缓冲区满时,或者关闭程序时,再将缓冲区中的数据全部写入磁盘。写入缓存的速度远远大于写入磁盘的速度,CPU将数据写入缓存后就可以干别的事情了,不用等待写入磁盘。
缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
在Java输入输出操作中会经常使用缓冲区,大家一定要理解这个概念。
本文介绍了文件的基本概念,包括文件的用途、文件与内存之间的数据交换过程,并解释了二进制文件与字符文件的区别。此外还介绍了Java中处理输入输出操作的基础类。
407

被折叠的 条评论
为什么被折叠?



