实验6 文件I/O练习

更新时间:2024-03-08 05:51:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验6 文件I/O练习

一. 实验目的

1. 通过阅读本课件知识点和例题,了解文件I/O的类型、原理、程序资源(类族)和编程方法。

2. 参考本课件对文件I/O类方法的描述及其给出的例题,寻找解决方案并编写程序,实现所要求的输入输出功能,以加深对本章内容的理解、提高文件I/O的实际运用能力。

二. 知识点和例题

1. 文件I/O的概念和分类

⑴ 什么是文件

文件是存储于外存储器 (如硬盘、U盘) 上 的一组信息的集合。文件在外存储器上以树形层次结构存储,由操作系统管理。例如在Windows资源管理器上“我的电脑”是树根,文件是树叶,期间有驱动器和一系列文件夹作为树杈。文件由文件名以及表示在树上位置的一个路径来标识,文件名由主名和表示文件类型的扩展名构成,例如:C:\\Documents and Settings\\Java\\MyProg.java

盘符 路径 文件名 扩展名 ⑵ 何谓及如何实现文件I/O

内存与文件的信息交换称为文件I/O,即从文件输入(I)和向文件输出文件也包括I/O设备,如打印机等。这些信息交换由程序来控制,不同的程序设计语言有不同的文件I/O控制方法。如C用fscanf/fprintf、fread/fwrite用fstream中的ifstream/ofstream对象; C#用stream类及其下面的一系列子类;则用InputStream/OutputStream、Reader/Writer类族来实现文件I⑶ 文件的类型

要正确实现文件I/O,必须根据文件的性质及I/O方式将文件分为几种不同的类型:文本文件——保存以ASCII、UNICODE等编码方式存储的文本。二进制文件——保存以二进制方式存储的数据,如整数、浮点数、声音、图像等。顺序读写文件——以顺序读写方式打开的文件,按照字节或进出数据的顺序进行读写。随机读写文件——以随机读写方式打开的文件,按照数据在文件中的位置(字节序号)进行定长数据的读写。

⑷ 流的概念

流 (stream) 是一组有序的、有起点和终点的字节集合,是对输入输出的抽象。的目的是使I/O操作与具体设备无关。对流的操作以字节为单位进行,并常常使用缓冲区(buffer)技术,这是因数据在内存中流动的速度要比文件存取的速度快得多,时间又与存取的频率成正比,为减小存取频率,系统让I/O先对缓冲区进行,满或文件关闭时,才发生物理的读入或写出。

⑸ 字节流和字符流

字节流是 Java 文件I/O的基本类型,即以字节为单位的、顺序方式的输入和输出。根据数据源、是否使用缓冲区,以及一次输入输出数据的类型等因素,在这种基本类型之上又派生出一系列子类型。

1

(O)。广义的等几套函数; C++Java/O。

引入流而文件存取的当缓冲区空、字符流是以字符为单位的I/O。由于Java使用的是UNICODE编码,因此单次输入输出的若是一个字节,则汉字等非英文字符将无法正确显示。根据是否有缓冲区等因素,字符流亦派生出一系列子类型。

⑹ 操作方式和类族

流操作方式 字节流类族 字符流类族 InputStream Reader 不使用缓冲区 OutputStream Writer BufferedInputStream FileReader 使用缓冲区 BufferedOutputStream FileWriter 将字节流转化为基本类型流 DataInputStream DataOutputStream 将字节流转化为字符流 InputStreamReader OutputStreamWriter 将流转化为String PrintStream PrintWriter 将字节流转化为对象流 ObjectInputStream ObjectOutputStream ⑺ 关于序列化

在面向对象程序中,有时我们需要把对象的数据(往往由各种不同的类型的数据项组成)按照原来的结构一并向文件写入,或从文件读出到对象中,并且将一个个对象的值首尾串接构成一个序列,怎样写入,就怎样读出,这种I/O方式称为序列化 (serialization)。由于不同类对象的数据结构不同,因此任何打算序列化的对象,其所属类都必须实现java.io.Serializable接口规范。

⑻ 文件I/O作业的一般流程 读操作 (I) 写操作 (O) 1 import java.io.*; import java.io.*; 2 try { try { 打开(open)一个流 打开(open)一个流 3 while (还有数据) { while (还有数据) { 读出数据; 写入数据; //其它处理 //其它处理 } } 4 关闭(close)打开的流 关闭(close)打开的流 } catch(IOException e) {} } catch(IOException e) {} 2. File类和JfileChooser类

⑴ File类概述

一个文件的信息分外部信息和内部信息,外部信息除了路径、文件名和扩展名之外,包括是否只读、是否隐藏等属性信息;内部信息则是文件中的内容。File类封装了文件的外部信息,并提供了对它的一系列操作,如修改文件属性、重命名等。除此之外,File的对象还用作流方法的参数,用来将流对象与物理文件绑定,例如:

2

还类File f = new File(\FileReader in = new FileReader(f); ⑵ File类的方法 ① 构造方法 方法原型 功能说明和实例 File(File parent, String child) 利用File对象与字符串构成的路径创建一个File对象,例如: File d = new File(\File f = new File(d, \File(String pathname) 利用字符串指定的路径和文件名创建一个File对象,例如: File f = new File(\File(String parent, String child) 利用字符串指定的路径和文件名创建一个File对象,例如: File f = new File(\File(URI uri) 利用URI对象创建一个File对象 ② 测试文件状态 方法原型 功能说明和实例 boolean exists() 测试File对象代表的文件是否存在,例如: if(f.exists()) { in = new FileReader(f);…} boolean isFile() 测试File对象是否代表文件 boolean isDirectory() 测试File对象是否代表文件夹 boolean isAbsolute() 测试File对象代表的是否为绝对路径 boolean isHidden() 测试File对象代表的是否为隐藏文件 boolean canRead() 测试File对象代表的文件是否为只读 boolean canWrite() 测试File对象代表的文件是否可写 ③ 测试文件属性

方法原型 功能说明和实例 String getName() 返回File对象代表的文件的名称,例如: File f = new File(\System.out.print(f.getName()); // 打印“06143.txt” long length() 返回File对象代表的文件的大小,例如: File f = new File(\System.out.print(f.length()); // 打印“2175” long lastModified() 返回File对象代表的文件的最近一次修改时间,可通过Date转换为可读格式 String getParent() 返回File对象代表的文件的上层文件夹 File getParentFile() 返回File对象代表的文件的上层文件夹相关的File对象 ④ 测试文件路径

3

方法原型 功能说明和实例 String getPath() 返回File对象所代表文件的路径总称, 如果创建时未设置,则返回文件名称 String getAbsolutePath() 返回File对象所代表文件的绝对路径: File f = new File(\System.out.println(f.getAbsolutePath()); String getCanonicalPath() 返回File对象所代表文件的规范路径: File f = new File(\try { System.out.println(f.getCanonicalPath()); } catch { } // 必须包含在try…catch块中 File getAbsoluteFile() 以File形式返回File对象所代表文件的绝对名称 File getCanonicalFile() 以File形式返回File对象所代表文件的规范名称 ⑤ 设置文件属性 方法原型 功能说明和实例 boolean renameTo(File dest) 将File对象代表的文件更名为dest代表的文件的名称,例如: File f = new File(\f.renameTo(newFile(\System.out.print(f.getName()); 经过这一操作后,磁盘上的文件被改名,但对象f的值不变 boolean setReadOnly() 将File对象代表的文件更改为具有只读属性 boolean setLastModified(long time) 设置File对象所代表的文件的最近一次修改时间 ⑥ 创建和删除文件夹 方法原型 功能说明和实例 boolean mkdir() 创建一个文件夹,并以File对象中的文件名作为文件夹名,例如: File f = new File(\f.mkdir(); // 在e:盘根目录下创建文件夹\boolean mkdirs() 创建一个包含有上层文件夹的文件夹,并以File对象中的路径作为文件夹名,例如: File f = new File(\f.mkdirs(); // 在e:盘下创建 \\Java\\workspace boolean delete() 删除File对象代表的文件或文件夹,例如: File f = new File(\f.delete(); void deleteOnExit() 程序结束时删除File对象代表的文件或文件夹 ⑦ 列出文件

4

方法原型 功能说明和实例 String[] list() 返回File对象所代表的文件夹下的文件和文件夹 String[] list(FilenameFilter filter) 返回File对象代表的文件夹下、符合给定文件名约束条件的文件和文件夹 File[] listFiles() 返回File对象代表的文件夹下所有File对象 File[] listFiles(FileFilter filter) 返回File对象代表的文件夹下符合给定内部信息约束条件的File对象 File[] listFiles(FilenameFilter filter) 返回File对象代表的文件夹下符合给定文件名约束条件的File对象 static File[] listRoots() 列出所有可取得的文件系统的根目录 ⑶ JFileChooser类概述

JFileChooser类是Swing类库中的一个成员, Swing类库是Sun开发的一个图形用户界面工具包,将在“用户界面”一章详细介绍,这里引入JFileChooser类的目的是想配合类,让用户在一个可视化的环境下对所需文件进行选择,这样,作业Student中的文件”也就不必写入源程序了。

要使用JFileChooser类,需要在源文件头部使用以下语句:

import javax.swing.JFileChooser;

⑷ JFileChooser的方法 ① 构造方法 方法原型 功能说明 JFileChooser() 在默认目录下选择文件 JFileChooser(File currentDirectory) 在File代表的目录下选择文件 JFileChooser(File currentDirectory, 利用FileSystemView在当前FileSystemView fsv) 目录下选择文件 JFileChooser(FileSystemView fsv) 利用FileSystemView选择 JFileChooser(String currentDirPath) 在指定目录下选择文件 JFileChooser(String currentDirPath, 利用FileSystemView在指定FileSystemView fsv) 的目录下选择文件 ② 打开窗口 方法原型 功能说明 int showOpenDialog(Component parent) 打开一个“Open”文件对话框 int showSaveDialog(Component parent) 打开一个“Save”文件对话框 int showDialog(Component parent, String approveButtonText) 自定义Open或Save按钮文本 showOpenDialog的返值及其意义:

JFileChooser.APPROVE_OPTION 用户点击取消以外的按钮 JFileChooser.CANCEL_OPTION 用户点击取消按钮 JFileChooser.ERROR_OPTION 发生错误或不正常关闭 ③ 选择文件

5

(GUI) File“06143.txt

方法原型 File getSelectedFile() File[] getSelectedFiles() boolean isMultiSelectionEnabled() 功能说明 返回被选中的文件 返回所有被选中的文件 返回是否允许多重选择 void setMultiSelectionEnabled(boolean b) 设置是否允许多重选择 ④ 设置外观 方法原型 void setApproveButtonText (String approveButtonText) void setApproveButtonToolTipText (String ToolTipText) File getCurrentDirectory() String getDialogTitle() ⑸ JFileChooser类应用实例

import java.io.*;

import javax.swing.JFileChooser; public class UseJFileChooser {

public static void main(String[] args) { File f = new File(\我的文档\

JFileChooser fileChooser = new JFileChooser(f); if (fileChooser.showOpenDialog(null) == FileChooser.APPROVE_OPTION) { f = fileChooser.getSelectedFile();

System.out.print(\您选择的文件是:\ }

else {

System.out.print(\用户取消\ } } }

功能说明 设置“确定”按钮的文字内容 设置“确定”按钮的ToolTip文字 返回代表当前目录的对象 返回文件设置窗口标题 3. 字节流类族

⑴ 层次结构图

FileOutputStream PipedOutputStream

OutputStream

FilterOutputStream ByteArrayOutputStream ObjectOutputStream

DataOutputStream BufferedOutputStream

PrintStream

6

FileInputStream

LineNumberInputStrea

PipedInputStream

DataInputStream

FilterInputStream

BufferedInputStream

InputStream

ByteArrayInputStream

PushBackInputStream

SequenceInputStream StringBufferInputStreaObjectInputStream

⑵ 抽象基类

① InputStream抽象类 方法 InputStream() int available() abstract int read() int read(byte[] b) long skip(long n) boolean markSupported() void mark(int readLimit) void reset() void close() ② OutputStream抽象类 方法 OutputStream() abstract void write(int data) void write(byte[] b) void flush() void close() ⑶ 文件字节流子类

这组子类分别继承自抽象基类InputStream和OutputStream,并将外部文件作为流的来源(数据源),即从文件读,向文件写。

文件名可由已创建的File对象给出,也可由一个字符串给出,例如文件名为1.txt,

7

功能 构造方法:创建字节输入流对象 测试有多少字节可供读取 抽象方法:读取一个字节 将读取的字节存入byte数组 读标志从数据源跳过n个字节 测试可否在数据源中加标记 在数据源的给定位置加标记 重置上次加注的标记 关闭数据源并释放资源 int read(byte[] b, int off, int len) 将自off读取len个字节存入数组 功能 构造方法:创建字节输出流对象 抽象方法:写出data中1字节数据 将byte数组中的数据写出 清空数据源对象 关闭数据源 void write(byte[] b, int off, int len) 从off开始写出数组中len字节数据 则:

File fi = new File(\

FileInputStream fis = new FileInputStream(fi); 或:

FileInputStream fis = new FileInputStream(\在创建该对象的同时,文件也被打开。

① FileInputStream子类 方法 功能 FileInputStream(File file) 创建以File对象作为数据源的对象 FileInputStream(String name) 创建以文件name作为数据源的对象 int available() 测试有多少字节可以从文件读取 int read() 从给定文件读取一个字节 int read(byte[] b) 读取数据放入byte数组, 并返回字节数 int read(byte[] b, int off, int len) 读取len个字节存入byte数组off位置 long skip(long n) 读标志从数据源跳过n个字节 boolean markSupported() 测试可否在数据源中加注标记 void mark(int readLimit) 在数据源的给定位置加注标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② FileOutputStream子类 方法 功能 FileOutputStream(File file) 创建以File作为数据源的对象 FileOutputStream(String name) 创建以name作为数据源的对象 FileOutputStream(String name, 创建以name作为数据源的对象并指出boolean append) 是否以追加的方式写出 void write(int data) 向给定文件写出一个字节 void write(byte[] b) 将byte数组中的数据写到文件 void write(byte[] b, int off, int len) 从off开始写出数组len字节数据 void flush() 清空数据源对象 void close() 关闭数据源 程序实例:

import java.io.*;

public class UseFileInputStream {

public static void main(String[] args) { File fi = new File(\ File fo = new File(\ try {

FileInputStream fis = new FileInputStream(fi); FileOutputStream fos = new FileOutputStream(fo);

8

int ch, n = fis.available(); for (int i = 0; i < n; i ++) { ch = fis.read(); fos.write(ch); }

fis.close(); fos.close(); }

catch (IOException e) {

System.err.println(e.getMessage()); }

}

}

⑷ 数组字节流子类

这组子类分别继承自InputStream和OutputStream,但使用一个字节数组byte[]ByteArrayInputStream中是作为构造方法参数表中的一个参数被;而在ByteArrayOutputStream中,则是作为类的属性被封装,即从给定的一个byte数组写。

对数组进行I/O的目的是:因为数组在内存中,I/O速度远比文件快得多,当程序需要I/O时,数组是最好的选择。

① ByteArrayInputStream子类 方法 功能 ByteArrayInputStream(byte[] d) 创建以byte数组作为数据源的对象 ByteArrayInputStream(byte[] d, 创建以byte数组作为数据源的对象,数据的int off, int len) 存储从off开始,使用len个字节 int available() 测试有多少字节可以从byte数组中读取 int read() 从byte数组读取一个字节 int read(byte[] b) 从byte数组读取数据到另一个byte数组 int read(byte[] b, 读取len字节数据存入byte数组off位置 int off, int len) long skip(long n) 读标志从数据源跳过n个字节 boolean markSupported() 测试可否在数据源中加注标记 void mark(int readLimit) 在数据源的给定位置加注标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② ByteArrayOutputStream子类 方法 功能 ByteArrayOutputStream() 默认构造方法 ByteArrayOutputStream(int size) 指定byte数组长度的构造方法 void write(int data) 向byte数组写出一个字节 void write(byte[] b) 将给定byte数组的数据写出到byte数组 9

作为流的来源,该字节数组在引用byte数组读;向封装在对象内部的一个高速度、非永久性的 void write(byte[] b, 从off开始写出len字节数据到byte数组 int off, int len) void flush() 刷新byte数组 void close() 关闭流 int size() 返回byte数组大小 byte[] toByteArray() 返回byte数组的引用 String toString() 将byte数组中的数据写到一个字符串 String toString(String encoding) 将byte数组中的数据按编码写到字符串 void writeTo(OutputStream out) 将byte数组中的数据写到另一个字节流 程序实例:

import java.io.*;

public class UseByteArrayInputStream {

public static void main(String[] args) {

byte[] src = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' }; ByteArrayInputStream bais = new ByteArrayInputStream(src); int n = bais.available(), i;

ByteArrayOutputStream baos = new ByteArrayOutputStream(n);

for (i = 0; i < n; i ++) baos.write(bais.read()); // 边读边写 for (i = 0; i < n; i ++) src[i] = (byte)(i + 'a'); // 更新数组 bais.reset(); // 重置bais

for (i = 0; i < n; i ++) System.out.print((char)bais.read());// System.out.println(); // 换一行

byte[] obj = baos.toByteArray(); // 将baos的数据取到数组obj for (i = 0; i < n; i ++)

System.out.print((char)obj[i]); // 打印obj } }

⑸ 具缓冲区的字节流子类

这组子类分别继承基类InputStream下的FilterInputStream子类以及OutputStreamFilterOutputStream子类,它们提供了针对各种数据源的缓冲输入输出功能。使用时

File fi = new File(\

FileInputStream fis = new FileInputStream(fi);

BufferedInputStream bis = new BufferedInputStream(fis); int ch = bis.read(); bis.close();

① BufferedInputStream子类 方法 功能 BufferedInputStream(InputStream stream) 创建有缓冲的InputStream对象 BufferedInputStream(InputStream stream, 创建有缓冲的InputStream对象并int size) 规定缓冲区大小 int available() 测试有多少个字节可供读取 10

打印下的只需将所使用的流对象作为参数提供给这组子类的构造方法,例如:

int read() 读取一个字节 int read(byte[] b) 读取放入byte数组, 返回字节数 int read(byte[] b, int off, int len) 读len字节存入byte数组off位置 long skip(long n) 读标志从数据源跳过n个字节 boolean markSupported() 测试可否在数据源中加注标记 void mark(int readLimit) 在数据源的给定位置加注标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 BufferedOutputStream子类 方法 功能 BufferedOutputStream(OutputStream stream) 创建有缓冲OutputStream对象 BufferedOutputStream(OutputStream stream, 创建有缓冲区的OutputStreamint size) 对象, 并规定缓冲区大小 void write(int data) 写出data中的一个字节 void write(byte[] b) 写出byte数组中的数据 void write(byte[] b, int off, int len) 写出数组从off始的len个字节 void flush() 清空数据源对象 void close() 关闭数据源

java.io.*;

class UseBufferedInputStream {

public static void main(String[] args) { File fi = new File(\ File fo = new File(\ try {

FileInputStream fis = new FileInputStream(fi); FileOutputStream fos = new FileOutputStream(fo);

BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos); int ch, n = bis.available(); for (int i = 0; i < n; i ++) { ch = bis.read(); bos.write(ch); }

bis.close(); bos.close(); }

catch (IOException e) {

System.err.println(e.getMessage()); } } 11

②程序实例:importpublic }

⑹ 串接成基本数据类型的字节流子类

字节流子类一次I/O仅为一个字节,显然不能满足基本数据类型的输入输出的需要。但通过序列化处理,Java 将各种基本类型的数据乃至对象串接成字节流,以二进制方式实现它们的输入输出。DataInputStream和DataOutputStream就是为此目的而设计的。

实现基本数据类型I/O的一系列方法是以接口(interface)方式定义的,这组类以及RandomAccessFile类(随机文件读写)实现了以二进制顺序方式进行I/O的接口DataInput和DataOutput。

① DataInputStream子类的方法 方法 功能 DataInputStream(InputStream stream) 创建有基本类型输入功能的流对象 int available() 测试有多少个字节可供读取 int read() 读取一个字节 int read(byte[] b) 将读取的字节存入byte数组 int read(byte[] b, int off, int len) 自off读len个字节存入byte数组 long skip(long n) 读标志跳过n个字节 boolean markSupported() 测试可否在数据源中加标记 void mark(int readLimit) 在数据源的给定位置加标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② DataInputStream子类实现的接口 接口规范 功能 boolean readBoolean() 读入一个逻辑型数据 byte readByte() 读入一个字节型数据 char readChar() 读入一个字符型数据 short readShort() 读入一个短整型数据 int readInt() 读入一个整型数据 long readLong() 读入一个长整型数据 float readFloat() 读入一个浮点型数据 double readDouble() 读入一个双精度型数据 int readUnsignedByte() 读入一个无符号字节型数据 int readUnsignedShort() 读入一个无符号短整型数据 void readFully(byte[] array) 读入所有数据存入byte数组 void readFully(byte[] array, int off, 读入len字节数据存入byte数组offint len) 位置 ③ DataOutputStream子类的方法 方法 功能 DataOutputStream() 创建有基本类型输出功能的流对象 void write(int data) 写出data中1字节数据 void write(byte[] b) 将byte数组中的数据写出 void write(byte[] b, int off, int len) 从off开始写出数组中len字节数据

12

void flush() 清空数据源对象 void close() 关闭数据源 ④ DataOutputStream子类实现的接口 接口规范 功能 void writeBoolean(boolean data) 写出一个逻辑型数据 void writeByte(byte data) 写出一个字节型数据 void writeChar(char data) 写出一个字符型数据 void writeShort(short data) 写出一个短整型数据 void writeInt(int data) 写出一个整型数据 void writeLong(long data) 写出一个长整型数据 void writeFloat(float data) 写出一个浮点型数据 void writeDouble(double data) 写出一个双精度浮点型数据 void write(byte[] array) 写出byte数组中的数据 void write(byte[] array,int off,int len) 从off开始写出数组中len字节数据 void writeBytes(String string) 写出字符串中的字节数据 void writeChars(String string) 写出字符串中的字符数据 程序实例(输出过程): import java.io.*;

public class UseDataOutput {

public static void main(String[] args) { byte byteData = 1; char charData = '2';

boolean boolTrue = true; boolean boolFalse = false; short shortData = 2; int intData = 4; long longData = 8;

float floatData = 3.1416f; double doubleData = 3.1416;

File file = new File(\ try {

FileOutputStream fileByteIO = new FileOutputStream(file);

DataOutputStream dataByteIO = new DataOutputStream(fileByteIO); dataByteIO.write(byteData); dataByteIO.writeByte(byteData); dataByteIO.writeBoolean(boolFalse); dataByteIO.writeBoolean(boolTrue); dataByteIO.writeChar(charData); dataByteIO.writeShort(shortData); dataByteIO.writeInt(intData); dataByteIO.writeLong(longData); dataByteIO.writeFloat(floatData);

13

dataByteIO.writeDouble(doubleData); dataByteIO.close(); }

catch (IOException e) {

System.out.println(\输出错误\ }

}

}

程序实例(输入过程): import java.io.*;

public class UseDataInput {

public static void main(String[] args) { File file = new File(\ try {

FileInputStream fileByteIO = new FileInputStream(file);

DataInputStream dataByteIO = new DataInputStream(fileByteIO); System.out.println(dataByteIO.read()); System.out.println(dataByteIO.readByte()); System.out.println(dataByteIO.readBoolean()); System.out.println(dataByteIO.readBoolean()); System.out.println(dataByteIO.readChar()); System.out.println(dataByteIO.readShort()); System.out.println(dataByteIO.readInt()); System.out.println(dataByteIO.readLong()); System.out.println(dataByteIO.readFloat()); System.out.println(dataByteIO.readDouble()); dataByteIO.close(); }

catch (IOException e) {

System.out.println(\输入错误\ } } }

⑺ 串接成字符串的字节流子类

Java中将字节流串接成为字符串的子类是PrintStream, 它继承了基类OutputStream FilterOutputStream 子类,并提供了一系列方法来输出文字或基本数据类型的数据,PrintStream的声明:

public class PrintStream extends FilterOutputStream 遗憾的是,这种以字符串形式进行I/O的类只有输出而没有输入,可能是由于托管方式

① PrintStream子类的构造方法和其它方法 方法 功能 PrintStream(OutputStream stream) 创建有字符串输出功能的输出流对象 14

下的不过都是以文本编码的字符串形式,以下是下某些无法逾越的技术障碍所导致。

PrintStream(OutputStream stream, 创建有字符串输出功能的输出流对象,Boolean autoflush) 并规定输出”\\n”之后是否清空 void write(int data) 写出data中1字节数据 void write(byte[] b) 将byte数组中的数据写出 void write(byte[] b, int off, int len) 从off始写出len字节数据 void flush() 清空数据源对象 void close() 关闭数据源 boolean checkError() 测试是否有错误检查功能 PrintStream子类的print方法 方法 功能 public void print(boolean data) 输出逻辑型数据 public void print(char data) 输出字符型数据 public void print(int data) 输出整型数据 public void print(long data) 输出长整型数据 public void print(float data) 输出浮点型数据 public void print(double data) 输出双精度浮点型数据 public void print(char[] data) 输出字符数组数据 public void print(String data) 输出字符串数据 public void print(Object data) 输出对象数据 PrintStream子类的println方法 方法 功能 public void println() 输出换行符(即换新行) public void println(boolean data) 输出逻辑型数据后换行 public void println(char data) 输出字符型数据后换行 public void println(int data) 输出整型数据后换行 public void println(long data) 输出长整型数据后换行 public void println(float data) 输出浮点型数据后换行 public void println(double data) 输出双精度型数据后换行 public void println(char[] data) 输出字符数组数据后换行 public void println(String data) 输出字符串数据后换行 public void println(Object data) 输出对象数据后换行

public static void main(String[] args) {

PrintStream ps = new PrintStream(System.out); // 此处是向屏幕输出 ps.println(true); ps.println('我');

ps.println(Integer.MAX_VALUE); ps.println(Long.MAX_VALUE);

15

②③程序实例:import java.io.*;

public class UsePrintStream {

}

}

ps.println(Float.MAX_VALUE); ps.println(Double.MAX_VALUE); ps.println(\我爱Java\

char[] data = {'我','爱','J','a','v','a'}; ps.println(data);

⑻ 串接成对象的字节流子类

ObjectInputStream和ObjectOutputStream可将对象序列化(serialization)为字节deserialization)为对象。由于不同类的数据结构不同,因此,java.io.Serializable接口规范。ObjectInputStream和ObjectOutputStream实现了接口ObjectInput和ObjectOutputDataInput和DataOutput继承来的,因此亦实现了基本数据类型的① ObjectInputStream子类 方法 功能 ObjectInputStream(InputStream in) 创建有对象输入功能的流对象 int available() 测试有多少字节可供读取 int read() 读取一个字节 int read(byte[] b) 读取一个字节 int read(byte[] b, int off, int len) 自off开始读取len个字节存入数组 Object readObject() (接口)读取一个对象的数据 long skip(long n) 读标志跳过n个字节 boolean markSupported() 测试可否在数据源中加标记 void mark(int readLimit) 在数据源的给定位置加标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② ObjectOutputStream子类 方法 功能 ObjectOutputStream() 创建有对象输出功能的流对象 void write(int data) 写出data中1字节数据 void write(byte[] b) 将byte数组中的数据写出 void write(byte[] b, int off, int len) 从off开始写出数组len字节数据 void writeObject(Object obj) (接口)写出一个对象的数据 void flush() 清空数据源对象 void close() 关闭数据源 程序实例:

import java.io.*;

class Point implements Serializable { // 可序列化的坐标点类 final static long serialVersionUID = 0; private int x, y; Point(int x, int y) {

,。16

流和从字节流反序列化(任何打算实现序列化存储的对象,其所属类都必须实现它们分别是从接口I/O

this.x = x; this.y = y; }

Point(Point p) { this.x = p.x; this.y = p.y; }

Point() {}

void setPoint(int x, int y) { this.x = x; this.y = y; }

int getX() { return x; } int getY() { return y; }

Point getPoint() { return this; } }

public class UseObjectStream {

public static void main(String[] args) { // 对象序列化测试程序 try {

FileOutputStream fos = new FileOutputStream(\ ObjectOutputStream oos = new ObjectOutputStream(fos); Point[] p = new Point[10];

for (int i = 0; i < 10; i ++) { p[i] = new Point(i, i + 1); oos.writeObject(p[i]); }

oos.close();

FileInputStream fis = new FileInputStream(\ ObjectInputStream ois = new ObjectInputStream(fis); for (int i = 0; i < 10; i ++) { p[i] = (Point)ois.readObject();

System.out.println(\ }

ois.close(); }

catch (Exception e) {

System.err.print(\ } } }

⑼ 控制台I/O流

① 控制台输出

PrintStream类的两个静态对象out和err: public static final PrintStream out; public static final PrintStream err;

17

作为System类的两个属性,允许其宿主类调用该类的方法print和println将字符串以及各种类型的数据输出到屏幕上,例如:

System.out.print(\输出字符串 System.out.println(3.1416); // 输出浮点数 ② 控制台字节输入

InputStream的一个静态对象in:

public static final InputStream in;

作为System类的一个属性,允许其宿主类调用该类的方法read,从键盘逐字节地输入数据到调用程序,以下是一个程序实例:

public class InputInteger {

public static int InputInt() { int ch = 0;

String str = \ try {

while((ch = System.in.read()) != 13) str += (char)ch; ch = System.in.read(); }

catch(Exception e) {

System.err.println(e.getMessage()); }

return Integer.parseInt(str); }

public static void main(String[] args) { System.out.print(InputInt()); } }

4. 字符流类族

⑴ 层次结构图

BufferedReader CharArrayReader InputStreamReader

Reader

FilterReader PipedReader StringReader

LineNumberReader

FileReader PushBackReader

18

BufferedWriter CharArrayWriter OutputStreamWriter

FileWriter

Writer

PrintWriter FilterWriter PipedWriter StringWriter

⑵ 抽象基类 ① Reader抽象类 方法 功能 Reader() 构造方法:创建字符输入流对象 boolean ready() 字符输入流对象是否已准备好 abstract int read() 抽象方法:读取一个字符 int read(char[] c) 将读取的字符存入字符数组 int read(char[] c, int off, int len) 将自off读取的len个字符存入数组 long skip(long n) 读标志从数据源跳过n个字符 boolean markSupported() 测试可否在数据源中加标记 void mark(int readLimit) 在数据源的给定位置加标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② Writer抽象类 方法 功能 Writer() 创建字符输出流对象 void write(int data) 写出data中1个字符 void write(char data) 写出字符data Abstract void write(char[] c, int off, int len) 从off始写出c中len个字符 void write(String string) 写出字符串 void write(String string, int off, int len) 从off始写出string中len个字符 abstract void flush() 清空数据源对象 void close() 关闭数据源 ⑶ 文件字符流子类

这组子类分别继承自抽象类Reader和Writer,并将外部文件作为流的来源(数据源),

19

即从文件读,向文件写。

文件名可由已创建的File对象给出,也可由一个字符串给出,例如文件名为1.txt,则:

File fi = new File(\FileReader fr = new FileReader(fi); 或:

FileReader fr = new FileReader(\在创建该对象的同时,文件也被打开。

① FileReader子类 方法 功能 FileReader(File file) 创建以File对象作为数据源的对象 FileReader(String name) 创建以文件name作为数据源的对象 boolean ready() 测试文件输入流对象是否已准备好 int read() 从给定文件读取一个字符 int read(char[] c) 读取数据放入char数组, 返回字节数 int read(char[] c, int off, int len) 读取len个字符存入char数组off位置 long skip(long n) 读标志从数据源跳过n个字符 boolean markSupported() 测试可否在数据源中加注标记 void mark(int readLimit) 在数据源的给定位置加注标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② FileWriter子类 方法 功能 FileWriter(File file) 创建以File作为数据源的对象 FileWriter(String name) 创建以name作为数据源的对象 FileWriter(String name, 创建以name作为数据源的对象并指出boolean append) 是否以追加的方式写出 void write(int data) 向给定文件写出data中一个字符 void write(char[] c) 将char数组中的数据写出到文件 void write(char[] c,int off,int len) 从off开始写出数组c中len个字符 void flush() 清空数据源对象 void close() 关闭数据源 程序实例

import java.io.*;

public class UseFileReaderWriter { public static void main(String[] args) { File fi = new File(\ File fo = new File(\ try { FileReader fr = new FileReader(fi); FileWriter fw = new FileWriter(fo);

20

}

}

int ch; while ((ch = fr.read()) != -1) { fw.write((char)ch); } fr.close(); fw.close(); }

catch (IOException e) { System.err.println(e.getMessage()); }

⑷ 数组字符流子类

这组子类分别继承自Reader和Writer,但用一个字符数组char[]作为流的来源,该字符数组在CharArrayReader中是作为构造方法参数表的参数被引用; 而在CharArrayWriter中,则是作为类的属性被封装,即:从给定的一个char数组读;向封装在对象内部的一个char数组写。

对数组I/O的目的是:因数组在内存中,I/O速度远比文件快得多,当程序需要高速度、非永久性的I/O时,数组是最好的选择。

① CharArrayReader子类 方法 CharArrayReader(char[] data) CharArrayReader(char[] data, int off, int len) boolean ready() int read() int read(char[] c) int read(char[] c, int off, int len) long skip(long n) boolean markSupported() void mark(int readLimit) void reset() void close() ② CharArrayWriter子类 方法 CharArrayWriter() CharArrayWriter(int size) CharArrayWriter append(char c) void write(int data) void write(String s, int off, int len) void write(char[] c, int off, int len)

功能 创建以char数组作为数据源的Reader对象 创建以char数组作为数据源的Reader对象,数据存储从off开始,使用len个字符 测试输入流对象是否已准备好 从char数组读取一个字符 从char数组读取数据到另一个char数组 读取len字符数据存入char数组off位置 读标志从数据源跳过n个字符 测试可否在数据源中加注标记 在数据源的给定位置加注标记 重置上次加注的标记 关闭数据源并释放资源 功能 默认构造方法 指定char数组长度的构造方法 向返回的流对象添加一个字符 向char数组写出一个字符 将字符串从off始,len个字符写到char数组 从off开始写出len个字符到char数组 21

void flush() void close() int size() char[] toCharArray() String toString() void writeTo(Writer out) 刷新char数组 关闭流 返回char数组大小 返回char数组的引用 将char数组中的数据写到一个字符串 将char数组中的数据写到另一个字符流 程序实例: import java.io.*;

public class UseCharArrayReaderWriter { public static void main(String[] args) { char[] src = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' }; int n = 10, i; CharArrayReader car = new CharArrayReader(src, 0, n); CharArrayWriter caw = new CharArrayWriter(); try { for (i = 0; i < n; i ++) caw.write(car.read()); // 边从car(src)读边向caw写 for (i = 0; i < n; i ++) src[i] = (char)(i + 'a'); // 更新数据源src car.reset(); // 重置流对象car for (i = 0; i < n; i ++) System.out.print((char)car.read()); // 打印car(src) } catch (Exception e) { System.err.println(e.getMessage()); } System.out.println(); // 换一行 char[] obj = caw.toCharArray(); // 将写入caw的数据取到char数组 for (i = 0; i < n; i ++) System.out.print(obj[i]); // 打印数组obj } }

⑸ 具缓冲区的字符流子类

这组子类分别继承自基类Reader和Writer, 它们提供了对各种数据源的缓冲读写功能。例如对于BufferedReader子类,FileReader的缓冲读写:

File f = new File(\FileReader fr = new FileReader(f);

BufferedReader br = new BufferedReader(fr); str = br.readLine(); br.close();

① BufferedReader子类

obj 下面的22

使用时需将流对象作为参数提供给它们的构造方法。代码提供了对 方法 功能 BufferedReader(Reader in) 创建有缓冲区的Reader对象 BufferedReader(Reader in, int size) 创建有缓冲的Reader对象,并规定缓冲区大小 boolean ready() 测试输入流对象是否已准备好 int read() 读取一个字符 int read(char[] b, int off, int len) 读取len个字符, 存入char数组off位置 String readLine() 读取整行数据放入一个字符串返回 long skip(long n) 读标志从数据源跳过n个字符 boolean markSupported() 测试可否在数据源中加注标记 void mark(int readLimit) 在数据源的给定位置加注标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② BufferedWriter子类 方法 功能 BufferedWriter(Writer out) 创建有缓冲区的Writer对象 BufferedWriter(Writer out, String encoding) 创建有缓冲区的给定字符编码的对象 void write(int data) 写出data中一个字符 void write(char[] b, int off, int len) 写出char数组中从off始的len个字符 void write(String s, int off, int len) 写出字符串从off开始的len个字符 void newLine() 写出一个换行符 void flush() 清空数据源对象 void close() 关闭数据源 程序实例: import java.io.*;

public class UseBufferedReaderWriter { public static void main(String[] args) { File fi = new File(\ File fo = new File(\ try { FileReader fr = new FileReader(fi); FileWriter fw = new FileWriter(fo); BufferedReader br = new BufferedReader(fr); BufferedWriter bw = new BufferedWriter(fw); int ch; while ((ch = br.read()) != -1) { bw.write(ch); } br.close(); bw.close(); } catch (IOException e) {

23

}

}

}

System.err.println(e.getMessage());

⑹ 序列化字节流的字符流子类

这组子类用字节流来提供字符处理的功能,只要将字节流作为参数提供给这组类的构造方法即可。后面的程序把作为System类属性的InputStream对象in放在InputStreamReader参数表中来创建InputStreamReader的对象,再将该对象放在BufferedReader的参数表中来创建BufferedReader的对象,便可以利用BufferedReader的readLine方法从键盘连续地输入数据到一个字符串。迄今为止,所有的实验中从键盘输入数据采用的都是这一方法。

① InputStreamReader子类 方法 功能 InputStreamReader(InputStream in) 创建序列化字节流的Reader对象 InputStreamReader(InputStream in, 创建序列化字节流的Reader对象,并规定String encoding) 字符的编码 boolean ready() 测试输入流对象是否已准备好 int read() 读取一个字符 int read(char[] c, int off, int len) 读取len个字符存入char数组off位置 String getEncoding() 返回使用的字符编码的名称 long skip(long n) 读标志从数据源跳过n个字符 boolean markSupported() 测试可否在数据源中加注标记 void mark(int readLimit) 在数据源的给定位置加注标记 void reset() 重置上次加注的标记 void close() 关闭数据源并释放资源 ② OutputStreamWriter子类 方法 功能 OutputStreamWriter(OutputStream out) 创建序列化字节流的Writer对象 OutputStreamWriter(OutputStream out, 创建序列化字节流的Writer对象, 并规定String encoding) 字符的编码 void write(int data) 写出data中一个字符 void write(char[] c, int off, int len) 写出char数组从off开始的len个字符 void write(String string, int off, int len) 写出字符串从off开始的len个字符 void newLine() 写出一个换行符 void flush() 清空数据源对象 void close() 关闭数据源 String getEncoding() 取得当前的编码方式 程序实例

import java.io.*;

public class UseStreamReaderWriter { public static void main(String[] args) {

24

InputStreamReader isr = new InputStreamReader(System.in); BufferedReader keyboard = new BufferedReader(isr); String strLow = \ try { System.out.print(\区间下限:\ strLow = keyboard.readLine(); System.out.print(\区间上限:\ strUp = keyboard.readLine(); }

catch (Exception e) { System.err.println(e.getMessage()); }

double low = Double.parseDouble(strLow); double up = Double.parseDouble(strUp);

System.out.println(\区间:从\到\

}

}

⑺ 串接成字符串的字符流子类

Java中将字符流串接成为字符串的子类是PrintWriter,它直接继承了基类Writer,并且

要注意的是:使用PrintWriter写出数据后必须调用close()关闭文件,才能使数据物理地PrintStream不同。

这种以字符串形式进行I/O的类只有输出而没有输入,可能是由于托管方式下某些无法

① PrintWriter子类的构造方法和其它方法 方法 功能 PrintWriter(Writer writer) 创建有字符串输出的字符输出流对象 PrintWriter(Writer writer, boolean flush) 同上。规定输出”\\n”之后是否flush PrintWriter(OutputStream out) 用OutputStream创建字符串输出对象 PrintWriter(OutputStream out, boolean flush) 同上,规定输出”\\n”之后是否flush void write(int data) 写出data中1个字符的数据 void write(char[] c) 将char数组中的数据写出 void write(char[] c, int off, int len) 从off开始写出len个字符的数据 void write(String data) 写出一个字符串 void write(String data, int off, int len) 从off开始写出len长度的字符串 void flush() 清空数据源对象 void close() 关闭数据源 boolean checkError() 测试是否有错误检查功能 ② PrintWriter子类的print方法 方法 功能 public void print(boolean data) 输出逻辑型数据 25

提供了一系列方法输出文字或基本类型的数据,但都是以文本编码的字符串形式。输出到外部设备,这点与逾越的技术障碍所导致。

public void print(char data) 输出字符型数据 public void print(int data) 输出整型数据 public void print(long data) 输出长整型数据 public void print(float data) 输出浮点型数据 public void print(double data) 输出双精度浮点型数据 public void print(char[] data) 输出字符数组数据 public void print(String data) 输出字符串数据 public void print(Object data) 输出对象数据 ③ PrintWriter子类的println方法 方法 功能 public void println() 输出换行符(即换新行) public void println(boolean data) 输出逻辑型数据后换行 public void println(char data) 输出字符型数据后换行 public void println(int data) 输出整型数据后换行 public void println(long data) 输出长整型数据后换行 public void println(float data) 输出浮点型数据后换行 public void println(double data) 输出双精度型数据后换行 public void println(char[] data) 输出字符数组数据后换行 public void println(String data) 输出字符串数据后换行 public void println(Object data) 输出对象数据后换行 程序实例: import java.io.*;

public class UsePrintWriter { public static void main(String[] args) { PrintWriter pw = new PrintWriter(System.out); pw.println(true); pw.println('A'); pw.write(65); // 用write输出’A’ pw.println(); pw.println(Integer.MAX_VALUE); pw.println(Long.MAX_VALUE); pw.println(Float.MAX_VALUE); pw.println(Double.MAX_VALUE); pw.println(\我爱Java\ pw.write(“我爱Java”); // 用write输出字符串 pw.println(); char[] data = {'我','爱','J','a','v','a'}; pw.println(data); pw.write(data); // 用write输出字符数组 pw.close(); // 用PrintWriter写出后必须关闭文件才能产生物理输出 } }

26

5. 随机读写文件

⑴ RandomAccessFile类

上两节介绍的字节流和字符流都是以顺序方式读写的,就是说,既不能在文件任意位置读写,也不能对同一文件又读又写。后两种方式属于随机读写方式,它需要使用RandomAccessFile类来实现。

RandomAccessFile与字节流和字符流都不属于同一类族,但它与DataInputStream和DataOutputStream都实现了DataInput以及DataOutput接口规范,因此,可以用同样的调用语法读写任意类型的二进制数据。

⑵ 构造方法和文件操作 方法 功能 RandomAccessFile(File file, 创建文件随机读写对象,文件名由File对象String mode) 给出,mode可以是“r”或“rw” RandomAccessFile(String name, 创建文件随机读写对象,文件名由name给出,String mode) mode可以是“r”或“rw” long getLength() 获取文件长度 long getFilePointer() 获取文件读写指针 void setLength(long newLength) 设置文件长度,可以与原文件不同 void seek(long pos) 设置文件读写指针 int skipBytes(int n) 文件读写指针跳过n个字节 void close() 关闭文件 ⑶ 随机读文件 方法 功能 int read() 读一个字节 int read(byte[] b, int off, int len) 读len个字节放在数组b从off开始处 int read(byte[] b) 读与数组b长度相等的字节放在b中 final int readFully(byte[], b) 读与数组b长度相等的字节放在b中 final void readFully(byte[] b, int off, int len) 读len个字节放在数组b从off开始处 boolean readBoolean() 读入1个字节作为布尔值 byte readByte() 读入1个字节作为有符号数 char readChar() 读入2个字节作为Unicode字符 short readShort() 读入2个字节作为短整型数 int readInt() 读入4个字节作为整型数 long readLong() 读入8个字节作为长整型数 float readFloat() 读入4个字节作为浮点数 double readDouble() 读入8个字节作为双精度数 String readLine() 读入一行作为字符串 ⑷ 随机写文件 方法 功能 void write(byte[] b) 把数组b中的数据写到文件 void write(byte[] b, int off, int len) 把数组b从off始len字节数据写到文件

27

void writeBoolean(boolean data) 把一个布尔值写到文件 void writeByte(byte data) 把data的值作为有符号数写出1字节到文件 void writeChar(char data) 把data的值作为字符写到文件 void writeShort(short data) 把data的值作为短整型数写到文件 void writeInt(int data) 把data的值作为整型数写到文件 void writeLong(long data) 把data的值作为长整型数写到文件 void writeFloat(float data) 把data的值作为浮点数写到文件 void writeDouble(double data) 把data的值作为双精度数写到文件 void writeBytes(String string) 把字符串写到文件 void writeChars(String string) 把按Unicode编码的字符串写到文件 ⑸ 程序实例 import java.io.*;

public class UseRandomAccessFile { public static void main(String[] args) { byte byteData = 1; boolean boolData = true; char charData = '2'; short shortData = 2; int intData = 4; long longData = 8; float floatData = 3.1416f; double doubleData = 3.1416; File f = new File(\ try { RandomAccessFile raf = new RandomAccessFile(f, \ raf.seek(32); raf.writeByte(byteData); raf.writeBoolean(boolData); raf.writeChar(charData); raf.writeShort(shortData); raf.writeInt(intData); raf.writeLong(longData); raf.writeFloat(floatData); raf.writeDouble(doubleData); raf.seek(32); System.out.println(raf.readByte()); System.out.println(raf.readBoolean()); System.out.println(raf.readChar()); System.out.println(raf.readShort()); System.out.println(raf.readInt()); System.out.println(raf.readLong()); System.out.println(raf.readFloat()); System.out.println(raf.readDouble());

28

raf.close(); }

catch (IOException e) { System.out.println(e.getMessage()); }

}

}

三. 作业

1. 通过阅读“知识点和例题”I/O的类型、原理、程序资源(类族)和编程方法。2. 在本课件中查找适当的方法并参考其程序实例,根据下列需求找到有效的解决方案并编写程序,在运行获得正确结果的基础上,将源代码拷入实验报告的“实验结果”一栏。⑴ 将文件06143.txt中的数据以顺序方式转储到一个二进制格式文件随机方式读出并显示在屏幕上。

⑵ 在实验5的基础上完成以下工作:① 将总评计算方法的选择改为直接从② 将数据文件的选择改为利用③ 以顺序方式从06143.bin④ 在Students类中求出平均分数、标准偏差和最高分得主,并按照总评成绩由高到低

对学生排序; ⑤ 将计算结果写入一个文本格式的文件,用记事本打开以验证其正确性。 Eclipse中编译运行)

System.in输入; JFileChooser的Open对话框; 利用JFileChooser的Save

,了解文件06143.bin,再以29

(必要时将程序实例拷入

中读取数据;对话框输入文件名,

本文来源:https://www.bwwdw.com/article/fe7a.html

Top