1. 文件的二进制思维是指
- 所有文件,不论是可执行文件、图片文件、视频文件、Word 文件、压缩文件、txt 文件,都没什么可神秘的,它们都是以 0 和 1 的二进制形式保存的
- 我们所看到的图片、视频、文本,都是应用程序对这些二进制的解析结果
2. 文件类型的概念
所有文件都是以二进制形式保存的,为了便于理解和处理文件,文件也有文件类型的概念
- 文件类型通常以扩展名的形式体现
- 每种文件类型都有一定的格式,代表着文件含义和二进制之间的映射关系
- 有的文件类型的格式是公开的,有的可能是私有的,也可以自己定义私有的文件格式
用户通过双击试图打开某扩展名的文件时,操作系统查找关联的应用程序,启动该程序,传递该文件路径给它,程序再打开该文件
给文件加正确的扩展名是一种惯例,但并不是强制的
3. 文件类型的分类
- 文件类型可以粗略地分为两类
- 文本文件:普通的文本文件(.txt)、程序源代码文件(.java)、HTML 文件(.html)等
- 二进制文件:压缩文件(.zip)、PDF 文件(.pdf)、MP3 文件(.mp3)、Excel 文件(.xlsx)等
4. 文本文件和二进制文件的区别
- 文本文件里的每个二进制字节都是某个可打印字符的一部分,都可以用最基本的文本编辑器进行查看和编辑,如 Windows 上的 notepad、Linux 上的 vi
- 二进制文件中,每个字节就不一定表示字符,可能表示颜色、字体、声音大小等。一般需要专门的编辑器进行查看和编辑
5. 不同操作系统下,文本文件的换行符是
- Windows 系统中,换行符一般是两个字符 “\r\n“,即 ASCII 码的
13('\r')
和10('\n')
- Linux 系统中,换行符一般是一个字符 “\n“
6. 不同操作系统下,文件系统的结构
- Windows 系统中,可以有多个逻辑盘,每个盘可以被格式化为一种不同的文件系统,常见的文件系统有 FAT32 和 NTFS
- Linux 系统中,只有一个逻辑的根目录,用斜线 / 表示。Linux 支持多种不同的文件系统,如 Ext2/Ext3/Ext4 等
- 不同的文件系统有不同的文件组织方式、结构和特点,一般情况下,不需要我们关心细节
7. 绝对路径、相对路径的概念
- 在 Windows 中,目录之间用反斜线 \ 分隔;在 Linux 中,目录之间用斜线 / 分隔
- 绝对路径:从根目录开始到当前文件的完整路径。在 Java 中,
java.io.File
类定义了一个静态变量File.separator
,表示路径分隔符,编程时应使用该变量而避免硬编码 - 相对路径:是相对于当前目录而言的。在命名行终端上,通过 cd 命令进入的目录就是当前目录。在 Java 中,通过
System.getProperty("user.dir");
可以得到运行 Java 程序的当前目录
8. 每个文件除了具体文本,还有哪些信息
- 元数据信息:文件名、创建时间、修改时间、文件大小等
- 是否隐藏:Windows 系统中,隐藏是文件的一个属性,可以进行设置;Linux 系统中,如果文件名以 . 开头,则为隐藏文件
- 访问权限:对所有者、用户组可以有不同的权限,具体权限包括读、写、执行
- 大小写是否敏感:Windows 系统中,一般是大小写不敏感的;Linux 系统 中,一般是大小写敏感的
- 临时文件:操作系统会有一定的策略自动清理不用的临时文件。临时文件一般不是用户手动创建的,而是应用程序产生的,用于临时目的
9. Java 中文件读写是怎样的
读写模式:文件是放在硬盘上的,程序处理文件需要将文件读入内存,修改后,需要写回硬盘。操作系统提供了对文件读写的基本 API,不同操作系统的接口和实现是不一样的。Java 封装了操作系统的功能,提供了统一的 API
- 基础知识:硬盘的访问延时,相比内存,是很慢的。操作系统和硬盘一般是按块批量传输,而不是按字节,以摊销延时开销,块大小一般为 512 字节,即使应用程序只需要文件的一个字节,操作系统也会至少将一个块读进来。一般而言,应尽量减少接触硬盘,接触一次,就一次多做了一些事情。对于网络请求和其他输入输出设备,原则都是类似的
- 基础知识:一般读写文件需要两次数据复制。比如读文件,需要先从硬盘复制到操作系统内核,再从内核复制到应用程序分配的内存中。操作系统运行所在的环境和应用程序是不一样的,操作系统所在的环境是内核态,应用程序是用户态。应用程序调用操作系统的功能,需要两次环境的切换,先从用户态切到内核态,再从内核态切到用户态。这种用户态/内核态的切换是有开销的,应尽量减少这种切换
缓冲区:为了提升文件操作的效率,应用程序经常使用缓冲区这一常见的策略
- 读文件时,即使目前只需要少量内容,但预知还会接着读取,就一次读取比较多的内容,放到读缓冲区,下次读取时,如果缓冲区有,就直接从缓冲区读,减少访问操作系统和硬盘
- 写文件时,先写到缓冲区,写缓冲区满了之后,再一次性调用操作系统写到硬盘。不过,需要注意的是,在写结束的时候,要记住将缓冲区的剩余内容同步到硬盘。操作系统自身也会使用缓冲区,不过,应用程序更了解读写模式,恰当使用往往可以有更高的效率
打开/关闭:操作系统操作文件一般有打开和关闭的概念。打开文件会在操作系统内核建立一个有关该文件的内存结构,这个结构一般通过一个整数索引来引用,这个索引一般称为文件描述符。这个结构是消耗内存的,操作系统能同时打开的文件一般也是有限的,在不用文件的时候,应该关闭文件。关闭文件一般会同步缓冲区内容到硬盘,并释放占据的内存结构
内存映射文件:操作系统一般支持一种称为内存映射文件的高效的随机读写大文件的方法
- 将文件直接映射到内存,操作内存就是操作文件
- 在内存映射文件中,只有访问到的数据才会被实际复制到内存,且数据只会复制一次,被操作系统以及多个应用程序共享
10. Java 中文件流的概念
流:Java 使用流这个概念处理所有的 IO,包括键盘、显示终端、网络等。流有输入流和输出流之分
- 输入流:可以从输入流中读取数据,输入流的实际提供者可以是键盘、文件、网络等
- 输出流:可以向输出流中写入数据,输出流的实际目的地可以是显示终端、文件、网络等
包:Java IO 的基本类大多位于包
java.io
中- 类
InputStream
表示输入流,OutputStream
表示输出流 - 类
FileInputStream
表示文件输入流,FileOutputStream
表示文件输出流
- 类
面向流的代码:一些实际上不是 IO 的数据源和目的地也转换为了流,以方便参与这种协作。比如,字节数组,也包装为了流
ByteArrayInputStream
和ByteArrayOutputStream
11. Java 文件中的装饰器设计模式
- 作用:基本的流按字节读写,没有缓冲区,这不方便使用。Java 解决这个问题的方法是使用装饰器设计模式,引入了很多装饰类,对基本的流增加功能,以方便使用
- 基类:Java 中有很多装饰类,有两个基类:过滤器输入流
FilterInputStream
和 过滤器输出流FilterOutputStream
。它们有很多子类BufferedInputStream/BufferedOutputStream
: 对流起缓冲装饰的子类DataInputStream/DataOutputStream
: 可以按 8 种基本数据类型和字符串对流进行读写的子类GZIPInputStream/ZipInputStream、GZIPOutputStream/ZipOutputStream
: 可以对流进行压缩和解压缩的子类PrintStream
:可以将基本类型、对象输出为其字符串表示的子类
12. Java 中的 Reader/Writer
- 以
InputStream/OutputStream
为基类的流基本都是以二进制形式处理数据的,不能够方便地处理文本文件,没有编码的概念 - 能够方便地按字符处理文本数据的基类是
Reader
和Writer
。它们也有很多子类FileReader/FileWriter
: 读写文件的子类BufferedReader/BufferedWriter
: 起缓冲装饰的子类CharArrayReader/CharArrayWriter
: 将字符数组包装为Reader/Writer
的子类InputStreamReader/OutputStreamWriter
:将InputStream/OutputStream
转换为Reader/Writer
的子类PrintWriter
:将基本类型、对象输出为其字符串表示的子类
13. RandomAccessFile
的概念
- 大部分情况下,使用流或
Reader/Writer
读写文件内容,但 Java 提供了一个独立的可以随机读写文件的类RandomAccessFile
,适用于大小已知的纪录组成的文件 - 该类在日常应用开发中用得比较少,但在一些系统程序中用得比较多
14. Java 中 File
类的作用是
- 表示文件路径、文件元数据、文件目录、临时文件、访问权限管理等
15. Java 中 NIO
的概念
Java 还有一个关于 IO 操作的包
java.nio
,nio 表示 New IONIO 代表一种不同的看待 IO 的方式,它有缓冲区和通道的概念
- 利用缓冲区和通道往往可以达成和流类似的目的,不过,它们更接近操作系统的概念,某些操作的性能也更高
- 比如复制文件到网路,通道可以利用操作系统和硬件提供的 DMA 机制(Direct Memory Access,直接内存存取),不用 CPU 和应用程序参与,直接将数据从硬盘复制到网卡
除了看待方式不同,NIO 还支持一些比较底层的功能。比如内存映射文件、文件加锁、自定义文件系统、非阻塞式 IO、异步 IO 等
16. Java 中的序列化和反序列化概念
- 序列化:将内存中的 Java 对象持久保存到一个流中
- 反序列化:从流中恢复 Java 对象到内存
- 作用:一是对象状态持久化;二是网络远程调用,用于传递和返回对象
- Java 主要通过接口
Serializable
和类ObjectInputStream/ObjectOutputStream
提供对序列化的支持,基本的使用是比较简单的,但也有一些复杂的地方 - 不过,Java 的默认序列化有一些缺点,比如,序列化后的形式比较大、浪费空间,序列化/反序列化的性能也比较低,更重要的是,它是 Java 特有的技术,不能与其他语言交互
- JSON 是近几年逐渐流行的轻量级的数据交换格式,在很多场合替代了 XML,也非常容易阅读和理解。Java 对象也可以序列化为 JSON 格式,且与其他语言进行交互
- Java 主要通过接口