Java输入输出(IO)和流的基本概念

本文介绍了文件的基本概念,包括文件的用途、文件与内存之间的数据交换过程,并解释了二进制文件与字符文件的区别。此外还介绍了Java中处理输入输出操作的基础类。
我们对文件的概念已经非常熟悉了,比如常见的 Word 文档、txt 文件、源文件等。文件是数据源的一种,最主要的作用是保存数据。

在《 载入内存,让程序运行起来 》一文中我们提到,所有的文件(保存在磁盘)都要载入内存才能处理,所有的数据必须写入文件(磁盘)才不会丢失。数据在文件和内存之间传递的过程叫做 文件流 ,类似水从一个地方流动到另一个地方。数据从文件复制到内存的过程叫做 输入流 ,从内存保存到文件的过程叫做 输出流


图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类,我们先来看剩下的四个类:
  字节流 字符流
输入InputStreamReader
输出OutputStreamWriter

这四个类是所有IO类的父类,包含了一些通用的方法和属性,是我们讲解的重点;不过由于都是抽象类,不能直接实例化,所以实际开发中都是使用它们的子类。

另外,针对一些频繁的设备交互,Java 也预定了3个可以直接使用的流对象,不需要你再手动实例化,分别是:
  • System.in(标准输入),通常代表键盘输入。
  • System.out(标准输出):通常写往显示器。
  • System.err(标准错误输出):通常写往显示器。

缓冲区

缓冲区又称为缓存,它是内存空间的一部分。

当需要读取磁盘上的文件时,操作系统会开辟一个缓冲区(一块内存),把读出的数据先放在缓冲区,再从缓冲区中读取数据。这样,下次读取相同的数据时就不用“远征”到磁盘,可以直接从缓冲区中读取,提高IO速度。

反之也一样,向磁盘写入数据时也会开辟缓冲区,操作系统将数据发送到缓冲区,而不是直接发送到外部设备,当缓冲区满时,或者关闭程序时,再将缓冲区中的数据全部写入磁盘。写入缓存的速度远远大于写入磁盘的速度,CPU将数据写入缓存后就可以干别的事情了,不用等待写入磁盘。

缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

在Java输入输出操作中会经常使用缓冲区,大家一定要理解这个概念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值