第十章 数据输入与输出
- 输入流与输出流:
(1)输入流:以程序为基准,向程序中输入数据的流定义为输入流。从输入流向程序中输入数据称为读数据(read)。
(2)输出流:以程序为基准,从程序输出数据的流称为输出流。从程序中将数据输出到输出流称为写数据(write)。 - 字节流和字符流
(1)字节流:按照字节的形式读/写数据。Java中抽象类InputStream和OutputStream及其派生子类用来处理字节流的输入和输出。
(2)字符流:按照字符的形式读/写数据。Java中抽象类Reader和Writer及其派生子类用来处理字符流的输入与输出。
(3)系统提供用于标准输入、输出的System类,以及用来解析各种类型数据(如整数、浮点数、字符串等)的Scanner类。
(4)虽然Java从本质上说是将输入/输出流分成字节流和字符流,但并不表示只能以这两种最低级的形式来处理输入/输出数据。事实上,还可以通过调用很多类的构造方法和成员方法来输入/输出各种类型的数据。 - 字节与字符输入/输出流类
(1)字节输入流类InputStream:用于以字节形式从数据源中读取数据。它是所有字节输入流类的父类。是一个抽象类,不能被实例化。主要派生子类包括:FileInputStream(按字节读取文件中的数据)、BufferedInputStream(将按字节形式读入的数据保存到缓冲区)等。层次结构如下:
InputStream
ByteArrayInputStream
FileInputStream
FilterInputStream
BufferedInputStream
DataInputStream
LineNumberInputStream
PushbackInputStream
ObjectInputStream
PipedInputStream
SequenceInputStream
StringBufferInputStream
其中,BufferedInputStream是一个非常有用的类,它可以缓冲输入的数据,从而提高数据的输入效率。其构造方法为:public BufferedInputStream(InputStream in)。其中,in可以是文件输入流或键盘输入流。该类的几个主要方法有:
a. public void close():关闭此输入流并释放与该流关联的所有系统资源。
b. public abstract int read():从输入流中读取数据的下一个字节。返回值为整数,如果到达流的末尾,则返回-1。
c. public int read(byte[] b):将从输入流读取的内容存储在字节数组b中。返回值为读入的字节数。如果到达流末尾不再有数据可用,则返回-1。
备注:从键盘输入数据时(即数据源为System.in),read()方法被阻塞,直至按回车键。如果按【Ctrl+Z】组合键,表示输入流结束,此时改行输入的内容均被忽略,read()返回值为-1。读取文件时(数据源为FileInputStream类对象),如果到达文件结尾,read()方法返回值为-1。
(2)字节输出流类OutputStream:用于以字节形式将数据写入目的地。主要派生子类包括:FileOutputStream(将数据写入文件)、PrintStream(用于输出各种类型的数据,如整数、浮点数、字符、字符串、布尔值等,其主要方法有print()和println())等。层次结构如下:
OutputStream
ByteArrayOutputStream
FileOutputStream
FilterOutputStream
BufferedOutputStream
DataOutputStream
PrintStream
ObjectOutputStream
PipedOutputStream
BufferedOutputStream类可以缓冲输出的数据,提高数据输出效率。该类的构造方法如下:
public BufferedOutputStream(OutputStream out)
表示创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
a. public void close():关闭此缓冲输出流并释放与此流有关的所有系统资源。
b. public void write(int b):将指定的字节写入此缓冲输出流。
c. public void write(byte[] b):将b.length个字节写入此缓冲输出流。
(3)字符输入流类Reader:以字符形式从数据源中读取数据。主要派生子类包括:InputStreamReader(读取字节数据并将其解码为字符)、FileReader(读取字符文件的内容)、BufferedReader(从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取)等。其层次结构如下:
Reader
BufferedReader
LineNumberReader
CharArrayReader
FilterReader
PushbackReader
InputStreamReader
FileReader
PipedReader
StringReader
其中,InputStreamReader类的构造方法为:public InputStreamReader(InputStream in);
其主要成员方法有:
a. public void close():关闭该流并释放与之关联的所有资源。
b. public int read():读取单个字符。
c. public int read(char[] c):将字符读入数组。返回值为读取的字符数。如果已到达末尾,则返回-1。
BufferedReader类的构造方法为:public BufferedReader(Reader in),它用于创建一个使用默认大小输入缓冲区的缓冲字符输入流。其成员方法与InputStreamReader类似,只是新增了一个readLine()方法,其声明方式和作用如下:
public String readLine():读取一个文本行。通过下列字符之一即可认为某行已终止:换行('\n')、回车('\r')或回车后直接跟着换行。其返回值为包含该行内容的字符串,并且不包含任何行终止符。如果已到达流末尾,则返回null。
(4)字符输出流类Writer:以字符的形式将数据写入目的地。Writer类是所有字符输出流类的父类,其主要派生子类包括:OutputStreamWriter(将字符以字节形式写入输出流)、FileWriter(将字符数据写入文件)、BufferedWriter(将字符数据写入缓冲区)、PrintWriter(格式化输出字符数据)等子类。其层次结构如下:
Writer
BufferedWriter
CharArrayWriter
FilterWriter
OutputStreamWriter
FileWriter
PipedWriter
PrintWriter
StringWriter
其中,OutputStreamWriter类的构造方法为:public OutputStreamWriter(OutputStream out);
其主要成员方法包括:
a. public void close():关闭此流。
b. public void write(int c):写入单个字符。
c. public void write(char[] c):写入字符数组。
d. public void write(String str):写入字符串。
BufferedWriter类的构造方法为:public BufferedWriter(Writer out);其主要成员方法包括:
a. public void close();关闭流。
b. public void write(int c);写入单个字符。
c. public void write(char[] c);写入字符数组。
d. public void write(String str);写入字符串。
e. public void newLine();写入一个行分隔符。 - 使用Scanner类输入各种类型的数据
Scanner类是一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器。该类的重要方法如下:
(1)nextByte()、nextShort()、nextInt()、nextLong()、nextFloat()、nextDouble()、nextBoolean()等方法分别用来读取字节、短整型、整型、长整型、浮点数、双精度浮点数和布尔值等。
(2)hasNextByte()、hasNextShort()、hasNextInt()、hasNextLong()、hasNextFloat()、hasNextDouble()、hasNextBoolean()等方法分别用来判断要读入的数据是否是字节、短整型、整型、长整型、浮点数、双精度浮点数或布尔值等。
(3)nextLine()方法用于读取一行数据,如果已用nextByte()、nextShort()等方法读取数据,此方法用于读取当前行中后续数据;hasNextLine()方法用于确认是否还有下一行数据,此方法主要针对文件,用于判断是否到达文件结尾处。
如果在一行中输入多个数据,可以用空格分割各数据。 - 掌握文件的读写与管理方法
(1)文件字节输入/输出流:指FileInputStream和FileOutputStream类,这两个类实现了对文件的顺序访问,并以字节为单位进行读/写操作。Java中,对文件的读/写操作主要步骤是:①.创建文件输入/输出流对象,此时文件自动打开或创建;②.用文件读写方法读写数据;③.关闭数据流,同时关闭了文件。
a. FileInputStream类:构造方法如下:
FileInputStream(String name)
FileInputStream(File file)
其中,name表示要打开的文件名,file表示文件类File的对象。例如:
//创建文件输入流对象,同时打开文件
FileInputStream fis = new FileInputStream("d:\\test.txt");
如果没有找到要打开的文件,系统会抛出FileNotFoundException异常。
b. FileOutputStream类:将数据写入文件,构造方法如下:
FileOutputStream(String name)
FileOutputStream(String name,boolean append)
FileOutputStream(File file)
其中,在FileOutputStream(String name)构造方法中,name表示要新建并打开的文件名;在FileOutputStream(String name,boolean append)构造方法中,参数append的值为true时,表示在原文件的尾部添加数据,否则将覆盖原文件的内容;在FileOutputStream(File file)构造方法中,file表示文件类File对象。例如:
//创建File类对象file
File file = new File("d:\\test.txt");
//基于File类对象file创建文件输出流类对象fos,新建d:\\test.txt对象
FileOutputStream fos = new FileOutputStream(file);
备注:FileInputStream类和FileOutputStream类继承了InputStream和OutputStream类的read()方法和write()方法,以便可以对打开的文件进行读/写操作。输入/输出流的程序都会抛出非运行时异常IOException,因此,必须在方法的声明处进行抛出,或者使用try-catch语句进行捕获。为了避免系统资源的浪费,当不再使用流时,需要使用close()方法关闭流,实际上就是关闭文件。
(2)文件字符输入/输出流
FileReader(File file)
FileReader(String filename)
FileWriter(String finename)
FileWriter(String filename,boolean append)
FileWriter(File file)
FileWriter(File file,boolean append)
其中,file是文件类File的对象;filename是要打开的文件名;当参数append值为true时,表示在原 文件的末尾添加数据,否则将覆盖原文件的内容。
(3)利用File类管理文件
Java中File类既可以表示文件又可以表示目录,它提供了操作文件或目录的一组方法。
a. 构造方法;
File(String pathname):通过将给定的路径字符串转换为抽象路径名来创建一个新File实例。
File(String parent,String child):根据parent路径名字符串和child路径名字符串创建一个新File实例。
File(File parent,String child):根据parent抽象路径名和child路径名字符串创建一个新File实例。
备注:抽象路径名实际上是一个字符串,它以"盘符:"开始,后面跟"\\路径名或文件名",其中,中间名称均表示目录,最后一个名称可以表示目录或文件。另外,抽象路径中的路径部分被称为父目录(parent)。由于"\\"是一个转义字符,所以"\\"实际上表示"\"。
b. 查询文件名和路径名
public String getName():返回此抽象路径名表示的文件或目录的名称。
public String getPath():将此抽象路径名转换为一个路径名字符串。
public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串。
public String getParent():返回此抽象路径名父目录的路径字符串。如果此路径名没有指定父目录,则返回null。
c. 抽象路径查询
public boolean exists():测试此抽象路径名表示的文件或目录是否存在。如果存在,返回true;否则,返回false。
public boolean isDirectory():测试此抽象路径名表示的是否是一个目录。如果是返回true;否则返回false。
public boolean isFile():测试此抽象路径名表示的是否是一个标准文件。如果是返回true;否则返回false。
public boolean isHidden():测试此抽象路径名表示的是否是一个隐藏文件。如果是返回true;否则返回false。
d. 文件与目录操作
public boolean createNewFile():当且仅当不存在此抽象路径名指定的文件时,创建一个新的空文件。如果指定的文件不存在且创建成功,返回true;否则返回false。
public boolean mkdir():创建此抽象路径名指定的目录。如果创建成功,返回true;否则返回false。如果路径名有多层,必须确保前面路径有效。例如,嘉定File对象的内容为"c:\\abc\\xyz",则要调用mkdir()方法来创建xyz目录,必须首先确保"c:\abc"目录是存在的。唯有如此,才能在"c:\abc"目录下创建目录xyz。
public boolean delete():删除此抽象路径名表示的文件或目录。如果此抽象路径名表示一个目录,则该目录必须为空才能删除。当且仅当成功删除文件或目录时,返回true;否则返回false。
public String[] list():列出此抽象路径名表示的目录中的文件和目录。如果此抽象名表示的不是一个目录,那么此方法将返回null;否则将返回一个字符串数组,每个数组元素对应目录中的一个文件或目录。
(4)使用RandomAccessFile类随机读写文件
字节输入/输出流和字符输入/输出流都是顺序读/写文件的,而RandomAccessFile类提供了随机访问文件的方法。RandomAccessFile类与输入/输出流类有两个不同点:
a. RandomAccessFile类直接继承了对象类Object,同时实现了DataInput接口和DataOutput接口,所以RandomAccessFile类既可以作为输入流,也可以作为输出流。
b. RandomAccessFile类定义了一个文件当前位置指针,文件的读取都是从文件当前位置指针指示的位置开始的。通过移动这个指针,就可以从文件的任何位置开始进行读/写操作。与此同时,系统在从文件中读取数据或向文件中写入数据时,位置指针会自动移动。
c. 构造方法
RandomAccessFile(File file,String mode)
RandomAccessFile(String name,String mode)
其中,file是一个文件对象;mode是访问方式,有三个值:r(读)、w(写)、rw(读写)。例如下面语句创建了随机存取文件对象rd,文件名为a.txt,文件属性为只读。
RandomAccessFile rd = new RandomAccessFile("a.txt",r);
d. 常用方法
public long getFilePointer():返回文件指针的位置;
public long length():返回文件的长度;
public void seek(long pos):将文件指针移到pos位置;
public int skipBytes(int n):使文件指针跳过n个字节;
public void close():关闭此随机访问文件流并释放与该流关联的所有系统资源;
public int read():从此文件中读取一个数据字节。以整数形式返回此字节,返回在0到255之间;
public int read(byte[] b):将最多b.length个数据字节从此文件读入byte数组;
public final char readChar():从此文件当前指针处读取一个字符(两个字节);
public final double readDouble():从此文件当前指针处读取一个Double型数据(8个字节);
public final float readFloat():从此文件当前指针处读取一个Float型数据(4个字节);
public final int readInt():从此文件当前指针处读取一个有符号的32位整数(4)个字节。类似的,系统提供了readLong()方法(8个字节),readShort()方法(2个字节)等;
public void write(int b):从文件当前指针位置开始,向文件写入指定的字节;
public void write(int[] b):从当前文件指针位置开始,将b.length个字节从指定byte数组写入文件;
https://blog.51cto.com/linyingkun/1643508