zoukankan      html  css  js  c++  java
  • 从零开始学Java 第15章 Java输入输出流

    第15章  Java输入输出流
    Java提供了完善的输入输出功能,即I/O功能。用于处理键盘输入、文件读取、写入以及网络传输数据等事件。Java的输入输出流是非常复杂的,本章将会对Java的文件系统、各类输入输出流以及对象序列化进行介绍。通过本节的学习读者会对Java的输入输出流有清晰的认识。
    15.1  I/O基础
    在正式介绍Java输入输出流之前需要一些基本概念的介绍。这一节的主要内容就是介绍Java中的I/O基础。主要包括流的概念,Java中流的分类以及Java的File类,通过File类可以方便的进行文件管理。学习完本节内容后就可以对Java的输入输出流机制有一个大体的了解了。
    15.1.1  流的概念
    在Java中是通过流来实现输入输出的,流是对各类信息的抽象概念。可以把流看作是Java输入输出系统与目标之间的管道。
    Java可以通过流从目标读取数据,或者通过流把数据写入目标。Java的I/O流可以连接多种目标,包括键盘等输入设备、显示器等输出设备以及磁盘和网络。
    Java中的输入流是指读取数据的来源,可以从一个输入流中读取数据。输出流是可以把数据写入的流,通过输出流可以把信息输出到显示器、硬盘以及网络。
    15.1.2  字节流和字符流
    字节流:字节流主要用于以字节为基本单位的输入输出。主要处理字节或者二进制数据的各种输入输出。一般用于处理图像、声音文件。
    字符流:字符流是以字符为输入输出处理的基本单位。主要用于处理字符或是文本类型的输入输出流。一般用作处理文本文件读取存储以及与网络的文本信息的交互。
    对应与Java中的字节流的输入输出类为InputStream类和OutputStream类。下面对该类进行详细的分析。
    1. InputStream类
    2. OutputStream类
    3. Reader类
    4.Writer类

    15.1.3  文件管理
    本章主要对Java的I/O进行介绍,通常情况下,I/O都是和文件相关的。本小节主要对Java中File类的使用,通过它可以进行文件目录的获取以及对目录和文件管理。
    15.2  字节流相关类
    本节主要对Java中相关的各种字节流进行介绍,通过一些简单的例子进行简单的展示。主要的字节流类有FileInputStream、FileOutputStream、ByteArrayInputStream、ByteArrayOutputStream、过滤字节流等类。
    15.2.1  文件输入流FileInputStream
    FileInputStream创建一个InputStream,从文件系统的某个文件中获取输入字节。它通常有两种构造方式:FileInputStream(File file)、FileInputStream(String name)。
    第一种是打开一个实际的文件来创建一个FileInputStream。该文件通过文件系统中File对象file来指定。另一方法是通过name来指定文件的路径。这两种方法都会抛出异常,如果指定的文件或路径不存在或者是一个目录的话,创建失败。会抛出FileNotFoundException异常。
    15.2.2  文件输出流FileOutputStream
    FileOutputStream创建一个可以将字节写入文件的输出流。它的常用构造函数有以下两种:FileOutputStream(File file)、FileOutputStream(String name)。
    15.2.3  字节数组输入流ByteArrayInputStream
    ByteArrayInputStream是把字节数组当作输入源的输入流,这种输入流有两种构造函数。下面是这两种形式:ByteArrayInputStream(byte [] buf)、ByteArrayInputStream(byte [] buf,int start,int num)。
    第一个构造函数是创建一个ByteArrayInputStream对象,使用buf作为其缓冲区数组。第二个构造函数是创建一个ByteArrayInputStream对象,以字节数组buf为缓冲数组,从start位置开始,长度为num的数组子集。
    ByteArrayInputStream实现了mark()和reset()方法。mark()方法用于标记流,reset()方法用于重置流。但是,如果makr()不被调用的话,reset()就返回到该流的起始位置。

    15.2.4  字节输出字节流ByteArrayOutputStream
    ByteArrayOutputStream是字节数组输出流,它把字节数组作为写入的目的地。该流的构造函数有下边两种形式:ByteArrayOutputStream()、ByteArrayOutputStream(int num)。
    第一种形式创建一个32字节的缓冲区,第二种形式创建一个大小为num字节的缓冲区。缓冲区被保存在buf数组中,buf的长度被保存在count中,buf和count都是受保护的。
    15.2.5  过滤字节流
    另外有常用的过滤字节流。包括过滤输入流FilterInputStream和过滤输出流FilterOutputStream的主要作用是在输入输出数据的同时对数据进行指定格式的转换。
    该流一般通过通用流的方法来访问的,即过滤类的超类。典型的扩展是缓冲、字符转换和原始数据转换。它们的构造函数如下:FilterInputStream(InputStream is)、FilterOutputStream (OutputStream os)。这些类提供的方法与InputStream和OutputStream中的方法一样。
    15.2.6  缓冲输入流BufferedInputStream
    对于面向字节的流来说,缓冲流是一个扩展的过滤流类。它通过把内存缓冲区连接到输入输出流来扩展的。这个缓冲区中,可以对多个字节同时进行输入输入输出操作,可以提高程序的性能。通过缓冲区,可以实现流的跳过、标记和重置操作。
    缓冲字节流有BufferedInputStream和BufferedOutputStream。另外,PushbackInputStream也实现了缓冲流。
    15.2.7  缓冲输出流BufferedOutputStream
    在BufferedOutputStream中除了有OutputStream中提供的方法,增加了一个flush()方法。这样可以确保数据缓冲区内的数据被写到实际的输出设备中。在BufferedOutputStream中是通过减少系统写数据时间来提高性能的,可以通过flush方法写出缓冲区中的数据。BufferedOutputStream的构造函数有两个:
    BufferedOutputStream(OutputStream os)
    BufferedOutputStream(OutputStream os,int bufsize)
    第一个构造函数产生一个默认长度为512自己的缓冲流。第二种形式通过bufsize指定缓冲区的的大小。
    15.2.8  回退输出流PushbackInputStream
    通过缓冲区可以实现的另一个功能是回退。回退是从输入流中读取一个字节然后把它返回到流中,PushbackInputStream类实现了这个功能。PushbackInputStream类的构造函数有两种形式:PushbackInputStream(InputStream is)、PushbackInputStream(InputSteam is,int num)。第一种形式创建一个流对象,它支持返回一个字节到输入流。第二种形式创建了具体num长度的缓冲区的回退缓冲流。
    15.2.9  数据流DataOutputStream和DataInputStream
    DataOutputStream和DataInputStream是两个非常有用的类。它们分别继承自FilterOutputStream和FilterInputStream。这两个流可以提供流按照与机器无关的读写能力。通过该流读写的数据与所在的机器无关,比较适合在网络上使用该流。它们的构造函数如下:
    DataOutputStream(OutputStream os)
    DataInputStream(InputStream is)
    该类的使用这里不再举例说明,读者可以自行查阅相关的API来熟悉它的使用。
    15.2.10  随机访问文件类RandomAccessFile类
    RandomAccessFile提供了一个能随机存取的文件类。该类不是从InputStream或是OutputStream中扩展的。但是它实现了定义输入输出方法的DateInput和DateOutput接口。它的构造函数如下:
    RandomAccessFile(File file,String mode)
    RandomAccessFile(String name,String mode)
    第一种形式中file指定了要打开的文件,第二个参数指定打开的模式。如果值为“r”,以只读形式打开文件。如果为“rw”打开文件可以读取和写入。如果是“rws”打开文件可以读取和写入,并要求每个文件内容或元数据的更新都同步到基础存储设备。如果是“rwd”打开可以读取和写入还要求对文件内容的每个更新都同步写入到基础存储设备。第二种形式的name指定文件的名字,第二个参数跟第一种形式相同。

    15.3  字符流相关类
    前一节介绍了Java中具体的一些字节流,这一节将介绍Java中的字符流类。字节流不能直接处理Unicode码。Java要想实现“一次编写,各处运行”就必须提供的对Unicode码的支持,字符流就是在这种情况下诞生的。本节将要介绍的几个字符流类,它们都扩展子Reader类和Writer类,关于这两个类前面已经进行了介绍。请读者回顾下前面的内容。
    15.3.1  字符输入流InputStreamReader
    InputStreamReader是字节流通向字符流的桥梁。它使用指定的字符集读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,否则可能接受平台默认的字符集。它的构造函数有下面几种形式:
    InputStreamReader(InputStream is)
    InputStreamReader(InputStream is,Charset cs)
    InputStreamReader(InputStream is,CharsetDecoder cs)
    InputStreamReader(InputStream is,String charSetName)

    15.3.2  字符输出流OutputStreamWriter
    OutputStreamWriter是字符流通向字节流的桥梁。使用指定的字符集将要向其写入的字符编码为字节。它使用的字符集可以由名称指定或显式给定,否则可能接受平台默认的字符集。
    每次调用write()方法的时候对要写入的字符调用编码器进行转换。在把它们写入基本输出流之前,会把它们先放到缓冲区存放。
    15.3.3  读文件类FileReader
    FileReader是一个可以方便的读取文件的类,它的直接父类是InputStreamReader。常用构造函数如下:FileReader(String filePath)和FileReader(File file)。第一种形式是通过路径来构建一个FileReader对象。第二种形式是通过File对象来创建一个FileReader对象。这两种形式创建出的对象都是使用系统默认的字符编码。

    15.3.4  写文件类FileWriter
    FileWriter用来向文件中写入字符的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在FileOutputStream上构造一个OutputStreamWriter。该类常用的构造函数有下面几种形式:
    FileWriter(File file)
    FileWriter(File , boolean append)
    FileWriter(String fileName)
    FileWriter(String filename,boolean append)

    15.3.5  读取缓冲类BufferedReader
    BufferedReader可以从输入流中读取文本。它通过缓冲去来改进字符、数组和行的读取效率。可以指定缓冲区的大小或者使用默认的缓冲区大小。它的构造函数如下:BufferedReader(Reader in)和BufferedReader(Reader in,in size)。第一种形式创建一个默认大小的缓冲字符流,第二种形式指定缓冲区的大小。
    BufferedReader提供了缓冲区实现回退的方法,即mark()和reset()方法。这样的话BufferedReader.markSuppored()的返回值为true。下面的程序是把一个文件字符流封装到缓冲字符流内读取文件,这样能提高读取的效率。
    15.3.6  写入缓冲类BufferedWriter
    BufferedWriter可以将文本写入字符输出流,缓冲各个字符。从而可以实现单个字符、数组和字符串的高效写入。它提供了一个方法flush()可以确保缓冲区写入到Writer。它的构造函数有下面的两种形式:BufferedWriter (Writer outputStream)和BufferedWriter (Writer outputStream,int bufSize)。
    第一种形式创建一个具有默认大小缓冲区的缓冲流。在第二种形式中,使用bufSize指定缓冲去的大小。

    15.4  对象序列化
    如果可以把对象保存或者能把对象直接在网络中传输的话,无疑可以提供强大的功能。Java提供了这种功能,即对象序列化。本节会对如何实现对象序列化,它的基本使用以及一些细节知识进行讲解。
    15.4.1  Serializable接口
    要想把对象序列化,对象所属的类必须实现Serializable接口。未实现此接口的类不能实现任何状态序列化。可序列化的所有类型的子类型都是可序列化的。该接口没有任何方法和字段,只是用于标示类是可序列化的作用。
    15.4.2  对象输入输出流
    要将对象写入到流中需要使用对象输入输出流,即ObjectOutputStream类和ObjectInputStream。ObjectOutputStream可以将Java对象写入OutputStream。可以使用ObjectInputStream读取(重构)对象。通过使用把流写入文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构该对象。这两个类的构造函数如下:
    ObjectOutputStream()
    ObjectOutputStream(OutputStream os)
    ObjectInputStream()
    ObjectInputStream(InputStream is)

    15.4.3  transient关键字
    在对象序列化的过程中,有的信息是不希望被写入进去的。例如把用户的登录信息包装成一个对象的话,它可能不希望密码被保存下来。这个问题的解决就需要使用transient关键字。关键字transient修饰的信息不被保存。可以看到程序运行的时候,在保存对象的文件中,重新读取中对象,对象的两个属性age和weight都没有保存。图15.9是程序的运行结果:
    15.5  小结
    本章主要介绍了Java的输入输出系统和对象序列化。也就是如何解决操作文件以及数据的传输问题,这些都是本章解决的问题。本章首先介绍了Java输入输出流的一些基本概念,如流的概念,什么是字节流,什么是字符流,文件类等知识。然后分别对Java输入输出流中的字节流和字符流进行了详细的介绍。在本章的最后对象序列化进行了介绍。希望通过本章的学习,读者可以深入的掌握Java输入输出流。

  • 相关阅读:
    打卡规则小模块设计
    json和ajax学习
    求两个数的百分比&时间格式化&ajax返回json
    spring security运行流程图(转)
    DelegatingFilterProxy作用浅析
    网站URL重写(Java UrlRewrite 的使用)
    JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
    JQuery 的Ajax的使用
    servlet程序HTTP Status 500
    CanvasRenderingContext2D.drawImage()无效,not working
  • 原文地址:https://www.cnblogs.com/yoogoo/p/2467277.html
Copyright © 2011-2022 走看看