Java知识

IO(输入输出字节流)

2019-08-19  本文已影响0人  不小心丢了

大多数应用程序都需要实现设备之间的数据传输,例如键盘可以输入数据,显示器可以显示程序等。在Java中,将这些通过不同输入输出设备(键盘、内存、显示器、网络等)之间的数据传输抽象表述为“流”,程序允许通过流的方式与输入输出设备进行数据传输。

IO流有很多种,按照操作数据不同,可以分为字节流和字符流,按照数据传输方向的不同又可以分为输入流和输出流程序从输入流中读取数据,向输出流中写入数据。在IO包中,字节流的输入输出流分别用java.io.InputStreamjava.io.OutputStream表示,字符流的输入输出分别用java.io.Readerjava.io.Writer表示。

IO流

字节流

字节流的概念

在计算机中,无论是文本、图片、音频还是视频,所有的文件都是以二进制(字节)形式存在的,IO流中针对字节的输入输出提供了一系列的流,统称为字节流。字节流是程序中最常用的流,根据数据的传输方向可将其分为字节输入流和字节输出流。在JDK中,提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类,所有的字节输入流都继承自InputStream,所有的字节输出流都继承自OutputStream

数据通过InputStream从源设备输入到程序,通过OutputStream从程序输出到目标设备,从而实现数据的传输。由此可见,IO流中的输入输出都是相对于程序而言的

InputStream常用方法

前三个read()方法都是用来读数据的,其中。第一个read()方法是从输入流中逐个读取字节,而第二个和第三个read()方法则将若干字节以字节数组的形式一次性读入,从而提高读取数据的效率。在进行IO操作结束后,应该调用close()方法关闭流,从而释放当前IO流所占的系统资源。

OutputStream常用方法

前三个是重载的write()方法,都用于向输出流写入字节,从而提高写数据的效率。flush()方法用来将当前输出流缓冲区(通常是字节数组)中的数据强制写入目标设备,此过程称为刷新。close()方法是用来关闭并释放与当前IO流相关的系统资源。

InputStream和OutputStream这两个类虽然提供了一系列和读取数据有关的办法,但是这两个类是抽象类,不能被实例化。

字节流读写文件

由于计算机中的数据基本都保存在硬盘的文件中,因此操作文件中的数据是一种很常见的操作。在操作文件时,最常见的就是从文件中读取数据并将数据写入文件,即文件的读写,针对文件的读写,JDK专门提供了两个类,分别是FileInputStream和FileOutputStream。FileInputStream是InputStream的子类,它是操作文件的字节输入流,专门用于读取文件中的数据。由于从文件读取数据是重复的操作,因此需要通过循环语句来实现数据的持续读取。

首先在Eclipse项目的根目录下创建一个文本文件test.txt,在文件中输入内容“itcast”并保存。然后创建一个读取文本文件的类。

创建的字节流FileInputStream通过read()方法将当前项目中的文件“test.txt”中的数据读取并打印。运行结果为105、116、99、97 、115和116。通常情况下读取文件应该输入字符,这里之所以输入数字是因为硬盘上的文件是以字节的形式存在的。在“text.txt”文件中,字符“i”、“t”、“c”、“a”、“s”、“t”各占一个字节,因此,最终显示的就是文件“text.txt”中6个字节所对应的十进制数。需要注意,在读取文件数据时,必须保证文件在相对应目录存在并且是可读的,否则会抛出文件找不到的异常FileNotFoundException

与FileInputStream对应的是FileOutputStream。FileOutputStream是OutputStream的子类,它是操作文件的字节输出流,专门用于把数据写入文件。

程序运行后。会在当前目录下生成一个新的文本文件example.txt(右键单击Refresh刷新),打开后会看到出现以下内容

通过FileOutputStream写数据时,自动创建了文件example.txt,并将数据写入,那么该文件中的数据首先会被清空,再写入数据。若希望在已经存在的文件追加内容则可使用FileOutputStraem(String fileName,boolean append)来创建文件输出流对象,并把append参数的值设置为true。

程序通过字节输出对象向文件“exampl.txt”写入“欢迎你!”后,并没有将文件之前的数据清空,而是将新写入的数据追加到了文件的末尾。

由于IO流在进行数据读写操作时会出现异常,为了代码的简洁,在上面的程序中使用了throws关键字将异常抛出。然而一旦遇到IO异常,IO留的的close()方法将无法得到执行,流对象所占用的系统资源将得不到释放,因此,为了保证IO流的close()方法必须执行,通常将关闭流的操作写在finally代码块中。

文件的拷贝

在应用程序中,IO流通常都是成对出现的,即输入流和输出流一起使用。例如文件的拷贝就需要通过输入流来读取文件中的数据,通过输出流将数据写入文件

首先在当前项目下创建文件夹source和target(右键NEW然后点击Folder),然后在source文件夹中存放一个“万能青年旅店 - 那个石家庄人.mp3”文件,拷贝文件的代码如下

程序运行结束后,刷新并打开target文件夹,发现source文件夹中的“万能青年旅店 - 那个石家庄人.mp3”成功拷贝到了target文件夹。在拷贝过程中,通过while循环将字节逐个进行拷贝。每循环一次,就通过FileInputStream的read()方法读取一个字节,并通过FileOutputStream的write()方法将该字节写入指定文件,循环往复,直到len的值为-1,表示读取到了文件的末尾,结束循环,完成文件的拷贝。

需要注意的是,在定义文件路径时使用了“\\”。这时因为在Windows中的目录符号为反斜杠“\”,但反斜杠“\”在java中是特殊字符,表示转义符,所以在使用反斜杠“\”时,前面应该再添加一个反斜杠,即为“\\”。除此之外,目录符号也可以用正斜线“/”来表示,如“source/万能青年旅店 - 那个石家庄人.mp3”。

字节流的缓冲区

上面的代码实现了文件的拷贝,但是一个字节一个字节的读取,需要频繁的操作文件,效率低,为了减少运输次数,可以定义一个字节数组作为临时缓冲区,,在拷贝文件时可以一次性读取多个字节的数据,并保存在字节数组中,然后将字节数组中的数据一次性写入文件。

在拷贝过程中,使用while循环语句逐渐实现字节文件的拷贝,每循环一次,就从文件读取若干字节填充字节数组,并通过变量len记住数组的字节数,然后从数组的第一个字节开始,将len字节一次写入文件。循环往复,当len值为-1时,说明已经读取到了文件的末尾,循环会结束,整个拷贝也就结束了。

字节缓冲流

在IO包中提供两个带缓冲流的字节流,分别是BufferedInputStream和BufferedOutputStream,它们的构造方法中分别接收InputStream和OutputStream类型的参数作为对象,在读取数据时提供缓冲功能

首先在Eclipse的项目目录下创建一个名称为example.txt的文件,并在该文件中写入内容;然后创建一个使用字节缓冲流拷贝该文件的类

上面的代码创建了BufferedInputStream和BufferedOutputStream两个缓冲流对象,这两个流内部都定义了一个大小为8192的字节数组。当调用read()或者write()方法读写数据时。首先将读取的数据存入定义好的字节数组,然后将字节数组的数据一次性读写到文件中。有效的提高了数据的读写效率。

上一篇下一篇

猜你喜欢

热点阅读