发信人: vivian (vivid), 信区: Training
标  题: JAVA语言入门(九)
发信站: 紫 丁 香 (Sun Jan 17 18:25:49 1999), 转信

第 九 章 Java输 入 输 出 操 作 

                                 9.1 Java 输 入 输 出 流 

所 有 的 程 序 语 言 都 提 供 与 本 机 文 件 系 统 交 互 的 方 式;Java也 不 例 外。 我 们 将 看 看Java是 怎 样 处 理
标 准 文 件 输 入 输 出 的(包 括stdin,stout,stderr)。 当 你 在 网 络 上 开 发 小 程 序 时, 你 必 须 注 意 直 接 文 件 输
入 输 出 是 不 安 全 因 素 的 关 键。 大 多 数 用 户 设 置 他 们 的 浏 览 器, 可 让 你 自 由 的 访 问 他 们 的 文 件
系 统, 但 有 些 不 让 你 访 问。 当 然, 如 果 你 开 发 你 内 部 的 应 用 程 序, 你 也 许 需 要 直 接 访 问 文 件。 

标 准 输 入 输 出 Unix的 用 户, 或 其 他 基 于 命 令 行 系 统 的 用 户(如DOS), 都 知 道 标 准 输 入 输 出 的 含
义。 标 准 输 入 文 件 是 键 盘, 标 准 输 出 文 件 是 你 的 终 端 屏 幕。 标 准 错 误 输 出 文 件 也 指 向 屏 幕, 如
果 有 必 要, 它 也 可 以 指 向 另 一 个 文 件 以 便 和 正 常 输 出 区 分。 

系 统 类 Java通 过 系 统 类 达 到 访 问 标 准 输 入 输 出 的 功 能。 上 面 提 到 的 三 个 文 件 在 这 个 系 统 类 中 实
现: Stdin System.in作 为InputStream类 的 一 个 实 例 来 实 现stdin, 你 可 以 使 用read()和skip(long n)两 个 成 员 函
数。read()让 你 从 输 入 中 读 一 个 字 节,skip(long n)让 你 在 输 入 中 跳 过n个 字 节。 

Stout System.out作 为PrintStream来 实 现stdout, 你 可 以 使 用print()和println()两 个 成 员 函 数。 这 两 个 函 数 支
持Java的 任 意 基 本 类 型 作 为 参 数。 

Stderr System.err同stdout一 样 实 现stderr。 象System.out一 样, 你 可 以 访 问PrintStream 成 员 函 数。 

                               9.2 标 准 输 入 输 出 例 子 

这 里 有 一 个 例 子, 功 能 象Unix里 的cat或type: 

import java.io.* class myCat{ public void main(String args[]) throws IOException{ int b; int count = 0; while ((b =
System.in.read()) != -1){ count++; System.out.print((char)b); } System.out.println(); //blank line
System.err.println("counted"+count+"total bytes."); } } 

                                 9.3 普 通 输 入 输 出 类 

除 了 基 本 的 键 盘 输 入 和 屏 幕 输 出 外, 我 们 还 需 要 联 系 文 件 的 输 入 输 出。 我 们 将 学 习 下 面 几 个
类: l FileInputStream l DataInputStream l FileOutputStream l DataOutputStream 

作 为 参 考, 再 列 出 一 些 特 定 应 用 的 类: l PipedInputStream l BufferedInputStream l PushBackInputStream l
StreamTokenizer l PipedOutputStream l BufferedOutputStream l RandomAccessFile 

我 们 不 在 此 讨 论 这 些 类, 但 你 可 以 在JAVA_HOME/src/java/io目 录 里 查 看 每 个 类 的 成 员 函 数 定 义。 

                                          9.4 文 件 

在 我 们 进 行 文 件 操 作 时, 需 要 知 道 一 些 关 于 文 件 的 信 息。File类 提 供 了 一 些 成 员 函 数 来 操 纵 文
件 和 获 得 一 些 文 件 的 信 息。 

                              9.4.1 创 建 一 个 新 的 文 件 对 象 

你 可 用 下 面 三 个 方 法 来 创 建 一 个 新 文 件 对 象: 

File myFile; myFile = new File("etc/motd"); 

或 

myFile = new File("/etc","motd"); //more useful if the directory or filename are variables 

或 

File myDir = new file("/etc"); myFile = new File(myDir,"motd"); 

这 三 种 方 法 取 决 于 你 访 问 文 件 的 方 式。 例 如, 如 果 你 在 应 用 程 序 里 只 用 一 个 文 件, 第 一 种 创
建 文 件 的 结 构 是 最 容 易 的。 但 如 果 你 在 同 一 目 录 里 打 开 数 个 文 件, 则 第 二 种 或 第 三 种 结 构 更
好 一 些。 

                                   9.4.2 文 件 测 试 和 使 用 

一 旦 你 创 建 了 一 个 文 件 对 象, 你 便 可 以 使 用 以 下 成 员 函 数 来 获 得 文 件 相 关 信 息: 

文 件 名 l String getName() l String getPath() l String getAbslutePath() l String getParent() l boolean renameTo(File newName) 

文 件 测 试 l boolean exists() l boolean canWrite() l boolean canRead() l boolean isFile() l boolean isDirectory() l boolean
isAbsolute() 

一 般 文 件 信 息 l long lastModified() l long length() 

目 录 用 法 l boolean mkdir() l String[] list() 

                               9.4.3 文 件 信 息 获 取 例 子 程 序

这 里 是 一 个 独 立 的 显 示 文 件 的 基 本 信 息 的 程 序, 文 件 通 过 命 令 行 参 数 传 输: 

import java.io.*; class fileInfo{ File fileToCheck; public static void main(String args[]) throws IOException{ if (args.length>0){
for (int i=0;i<args.length;i++){ fileToCheck = new File(args[i]); info(fileToCheck); } } else{ System.out.println("No file given."); }
} public void info (File f) throws IOException { System.out.println("Name: "+f.getName()); System.out.println("Path:
"=f.getPath()); if (f.exists()) { System.out.println("File exists."); System.out.print((f.canRead() ?" and is Readable":""));
System.out.print((f.cnaWrite()?" and is Writeable":"")); System.out.println("."); System.out.println("File is " + f.lenght() = "
bytes."); } else { System.out.println("File does not exist."); } } } 

                                         9.5 输 入 流

InputStream SequenceInputStream FileInputStream PipedInputStream ByteArrayInputStream FileterInputStream
StringBufferInputStream 

DataInputStream LineNumberInputStream PushbackInputStream BufferedInputStream 有 好 几 个 类 是 专 门 用 来 处 理 文
件 输 入 的。 下 面 是 文 件 输 入 类 的 层 次 结 构: 

                                  9.5.1 FileInputStream 对 象 

FileInputStream典 型 地 表 示 一 种 顺 序 访 问 的 文 本 文 件。 通 过 使 用FileInputStream你 可 以 访 问 文 件 的 一
个 字 节、 几 个 字 节 或 整 个 文 件。 

                                   9.5.2 打 开FileInputStream 

为 一 个 文 件 打 开 输 入 流FileInputStream, 你 必 须 将 文 件 名 或 文 件 对 象 传 送 给 结 构: 

FileInput Stream myFileStream; myFileStream = new FileInputStream ( "/etc/motd"); 

你 还 可 以 象 下 边 这 样 从FileInputStream里 读 文 件 信 息: 

File myFile ; FileInputSteam myFileStream; myFile = new File("/etc/motd"); myFileStream = new FileInputStream(myFile); 

一 旦FileInputStream输 入 流 打 开, 你 就 可 以 从 里 面 读 取 信 息 了。read()成 员 函 数 有 以 下 几 种 选 项: 

l int read() //reads one byte //return -1 at end of stream l int read(byte b[]) //fills entire array,if possible //returns number of bytes
read //returns -1 if end of stream is reached 

l int read(byte b[],int offset, int len) //reads len bytes into b starting at b[offset] //Returns number of bytes read, //or -1 if end of
stream is reached. 

                                   9.5.3 关 闭FileInputStream 

当 你 完 成 一 个 文 件 的 操 作, 你 可 选 两 种 方 法 关 闭 它: 显 式 关 闭 和 隐 式 关 闭, 隐 式 关 闭 是 自 动
垃 圾 回 收 时 的 功 能。 

显 式 关 闭 如 下: myFileStream.close(); 

                             9.6 例 程: 显 示 一 个 文 件 

如 果 文 件 的 访 问 权 限 足 够, 你 可 以 在TextArea对 象 里 显 示 文 件 内 容。 

下 面 是 显 示 文 件 的 程 序 片 断: 

FileInputStream fis; TextArea ta; public vod init(){ byte b[] = new byte [1024]; int I; //make it big enough or wait until you //know
the size of the file String s; try { fis = new FileInputStream("/etc/motd"); } catch(FileNotFoundException e) { /*do something
appropriate */ } try { I= fis.read(b); } catch(IOException e) { /* do something appropriate */ } s = new String(b, 0); ta = new
TextArea(s,5,40); add (ta); } 

                                  9.7 DataInputStreams

DataInputStreams与FileInputStreams差 不 多。Data流 可 以 直 接 读 任 意 一 种 变 量 类 型, 如浮 点 数, 整 数 和 字
符 等。 一 般 来 说, 对 二 进 制 文 件 使 用DataInputStream流。 

                             9.7.1 打 开 和 关 闭DataInputStreams

打 开 和 关 闭DataInputStreams对 象 时, 其 方 法 与FileInputStreams相 同: 

DataInputStreams myDataStream; FileInputStreams myFileStream; 

//get a file handle myFileStream = new FileInputStream("/usr/db/stock.dbf"); //open,or "chain" a data input file myDataStream =
new DataOutputStream(myFileStream); 

//Now we can use both input streams to access our file //j(If we want to...) myFileStream.read(b); I = myDataStrea.readInt(); 

//close the data friel explicityly //Always close the "topmost" file stream myDataStream.close(); myFileStream.close(); 

                                   9.7.2 读DataInputStreams 

当 你 从DataInputStreams流 里 访 问 文 件 时, 你 可 以 使 用 与FileInputStream流 相 同 的 成 员 函 数 read()。 但 你
也 可 以 使 用 其 他 访 问 方 法 来 读 取 不 同 种 类 的 数 据: 

l byte readByte() l int readUnsignedByte() l short readShort() l int readUnsighedShort() l char readChar() l int readInt l long
readLong() l float readFloat() l double readDouble() l String readLine() 

以 上 每 一 个 成 员 函 数 都 读 取 相 应 的 数 据 对 象。 象String readLine()成 员 函 数, 你 可 使 用\n,\r,\r\n,或EOF作
为 字 符 串 结 束 符。 

读 一 个 长 整 型, 例 如: 

long serialNo; ... serialNo = myDataStream.readLong(); 

                                     9.8 URL 输 入 流 

除 了 基 本 文 件 访 问 外,Java还 提 供 了 通 过 网 络 使 用URL访 问 对 象 的 功 能。 在 下 面 这 个 例 子 里, 我
们 用getDocumentBase()成 员 函 数 并 显 式 指 定URL对 象 来 访 问 声 音 和 图 象。 

String imageFile = new String ("images/Duke/T1.gif"); images[0] = getImage(getDocumentBase(),imageFile(); 

如 果 我 们 愿 意, 可 以 直 接 使 用URL: URL imageSource; imageSource = new URL("http://555-1212.com/~info");
images[0] = getImage(imageSource,"Duke/T1.gif"); 

我 们 可 以 为 相 应 的URL打 开 输 入 流。 例 如, 下 面 的 程 序 里 包 括 一 个 数 据 文 件: InputStream is; byte
buffer[] = new byte[24]; is = new URL(getDocumentBase(),dataname).openStream(); 

现 在 我 们 可 以 使 用is, 就 象 使 用FileInputStream对 象 一 样: is.read(buffer.0,buffer.length); 

注 意: 有 些 用 户 设 置 了 他 们 的 浏 览 器 安 全 属 性, 可 以 不 让 你 的 程 序 访 问 他 们 的 文 件。 

                                    9.9 OutputStreams 

上 面 我 们 谈 到 了 读 数 据, 那 么 如 何 实 现 写 数 据 呢? 象 输 入 流 一 样, 输 出 流 也 有 类 似 的 层 次 结
构: 

OutputStream 

FileOutputStream PipedOutputStream ByteArrayOutputStream FilterOutputStream 

DataOutputStream PrintStream BufferedOutputStream 

我 们 将 分 析FileOutputStream和DataOutputStream类 来 完 成 我 们 碰 到 的 输 出 流 问 题。 其 它 的 输 出 流 包 含
了 更 多 的 信 息 和 成 员 函 数。 象 输 入 流 的 源 文 件 一 样, 这 些 文 件 在 $JAVA_HOME/src/java/io目 录 下。 

                                   9.9.1 FileOutputStream类 

FileOutputStream对 象 用 于 向 一 个 文 本 文 件 写 数 据。 象 输 入 文 件 一 样, 你 得 先 打 开 这 个 文 件 后 才 能
写 这 个 文 件。 

                            9.9.2 打 开 一 个FileOutputStream对 象 

要 打 开 一 个FileOutputStream对 象, 象 打 开 一 个 输 入 流 一 样, 你 可 以 将 字 符 串 或 文 件 对 象 作 为 参
数: FileOutputStream myFileStream; myFileStream = new FileOutputStream("/etc/motd"); 

象 输 入 流 一 样, 你 也 可 这 样 使 用: File myFile; FileOutputStream myFileStream; myFile = new File("/etc/motd");
myFileStream = new FileOutputStream(myFile); 

                                      9.9.3 写 入 一 个 流 

一 旦 文 件 被 打 开, 你 便 可 以 使 用write()函 数 向 文 件 里 写 一 些 数 据。 就 象 输 入 流 的read()函 数 一 样,
你 可 有 三 种 方 法: l void write(int b);//writes out one byte l void write(byte b[]);//writes out entire array l void write (byte
b[],int offset,int length);//write out length bytes of b[],starting at b[offset] 

                            9.9.4 关 闭 一 个FileOutputStream对 象 

关 闭 输 出 流 和 关 闭 输 入 流 方 法 一 样, 你 可 以 使 用 显 式 方 法: myFileStream.close(); 你 也 可 以 让 系 统
自 动 关 闭 它。 

                                9.10 例 子: 存 储 信 息 

下 面 有 一 个 程 序, 让 用 户 输 入 一 些 姓 名 和 电 话 号 码。 每 一 个 姓 名 和 号 码 将 加 在 文 件 里。 用 户
通 过 点“Done"按 钮 来 告 诉 系 统 整 个 列 表 已 输 入 完 毕。 

一 旦 用 户 输 入 完 整 个 列 表, 程 序 将 创 建 一 个 输 出 文 件 并 显 示 或 打 印 出 来。 例 如: 

555-1212,Tom 123-456-7890,Peggy L. 234-5678,Marc 234-5678,Ron 876-4321,Beth&Brian 33.1.42.45.70,Jean-Marc 

下 面 是 程 序 的 源 代 码: import java.io.*; 

//Phones.java //A simple database creation program 

class Phones { static FileOutputStream fos; public static final int lineLength = 81; public static void main(String args[]) throws
IOExciption { byte[] phone = new byte[lineLength]; byte[] name = new byte[lineLenght]; int I; fos = new
FileOutputStream("phone.numbers"); while (true) { System.err.println("Enter a name (enter 'done' to quit)"); readLine(name); if
("done".equalsIgnoreCase(new String(name,0,0,4))) { break; } System.err.println("Enter the phone number"); readLine(phone);
for ( i=0;phone[i]!= 0;i++) { fos.write(phone[i]); } fos.write(','); for (i=0;name[i]!= 0;I++) { fos.write(name[i]); } fos.write('\n'); }
fos.close(); } 

private static void readLine(byte line[]) throws IOException { int i=0,b=0; 

while ((i<lineLengh-1))&&((b=System.ini.read())!='\n')) { line[i++] = (byte)b; } line[i]=(byte) 0; } } 

                                 9.11 BufferedOutput流 

如 果 你 处 理 的 数 据 量 很 多, 或 向 文 件 写 很 多 次 小 数 据, 你 可 以 使 用 一 个BufferedOutput流。
BufferedOutput流 提 供 和FileOutputStream类 同 样 的 写 操 作 方 法, 但 所 有 输 出 全 部 存 放 在 一 个 缓 冲 区
里。 当 你 填 满 缓 冲 区, 它 将 一 次 性 写 入 磁 盘。 或 者 你 主 动 将 缓 冲 区 写 入 磁 盘。 

                                 9.11.1 创 建BufferedOutput流 

如 果 要 创 建 一 个BufferedOutput流, 首 先 需 要 一 个FileOutput流。 然 后 将 缓 冲 区 链 接 到 FileOutput流:
FileOutputStream myFileStream; BufferedOutputStream myBufferStream; //get a file handle myFileStream = new
FileOutputStream("/usr/db/stock.dbf"); //chain a buffered output stream myBufferSSstream = new
BufferedOutputStream(myFileStream); 

                            9.11.2 更 新 和 关 闭BufferedOutput流 

和 普 通FileOutput流 一 样, 向BufferedOutput流 里 的 每 一 次 写 操 作 和 写 入 磁 盘 操 作 并 不 是 一 一 对 应 的。
要 想 在 程 序 结 束 之 前 将 缓 冲 区 里 的 数 据 写 入 磁 盘, 除 非 填 满 缓 冲 区, 否 则 只 有 显 式 调
用flush()函 数: //force left-over data to disk myBufferStream.flush(); //close the data file explicitly //Always close the "topmost"
file stream myBufferStream.close(); myFileStream.close(); 

                                    9.12 DataOutput流 

和DataInputStream对 应,Java还 提 供 了DataOutput流。 使 用DataOutput流, 我 们 可 以 向 文 件 写 入 二 进 制 数
据。 

                           9.12.1 打 开 和 关 闭DataOutput流 对 象 

打 开 和 关 闭DataOutput流 对 象 与 打 开、 关 闭FileOutput流 对 象 方 法 一 样: DataOutputStream myDataStream;
FileOutputStream myFileStream; BufferedOutputStream myBufferStream; 

//get a file handle mhyFileStream = new FileOutputStream("/usr/db/stock.dbf"); //chain a buffered output stream (for efficiency);
myBufferStream = new BufferedOutputStream(myFileStream); //chain a data output file myDataStream = new
DataOutputStream(myBufferStream); 

//Now we can use both input streams to access our file //(iiIf we want to ...) myBufferStream.write(b);
myDataStream.writeInt(i); 

//close the data file explicitly //Always colse the "topmost" file stream myDataStream.close(); myBuffersStream.close();
myFileStream.close(); 

                                9.12.2 向DataOutput流 写 数 据

FileOutput流 里 的write()函 数 各 种 方 法 都 适 用 于DataOutput流。 你 还 可 以 看 到DataInput流 的 类 似 函 数 方
法: l void writeBoolean (boolean v) l void writeByte (int v) l void writeShort (int v) l void writeChar (int v) l void writeInt (int v) l
void writeFloat (float v) l void writeDouble (double v) l void writeBytes (string s) l void writeChars (string s) 

对 字 符 串 来 说, 有 两 种 选 择:byte和char。 记 住byte是8位 数 据 而char是16位 数 据。 如 果 你 想 利
用Unicode字 符 的 优 点, 你 应 使 用writeChars()函 数。 

                                       9.12.3 输 出 记 数 

在 使 用 二 进 制 数 据 输 出 时 常 用 的 另 外 一 个 函 数 是size()。 这 个 函 数 返 回 写 入 文 件 数 据 的 总 字 节
数。 你 也 可 用size()函 数 将 数 据 文 件 分 成 四 字 节 为 单 位 的 块, 例 如: ... int bytesLeft =
myDataStream.size()%4; for (int I = 0; I< bytesLeft; I++) { myDataStrea.write(0); } ... 

                                  9.13 随 机 访 问 文 件

我 们 读 文 件 常 常 不 是 从 头 至 尾 顺 序 读 的。 你 也 许 想 将 一 文 本 文 件 当 作 一 个 数 据 库, 读 完 一 个
记 录 后, 跳 到 另 一 个 记 录, 它 们 在 文 件 的 不 同 地 方。Java提 供 了RandomAccessFile类 让 你 操 作 这 种
类 型 的 输 入 输 出。 

                                 9.13.1 创 建 随 机 访 问 文 件 

打 开 随 机 访 问 文 件 有 两 种 方 法: l 用 文 件 名 myRAFile = new RandomAccessFile(String name,String mode); l 用
文 件 对 象 myRAFile = new RandomAccessFile(File file,String mode); 

mode参 数 决 定 了 访 问 文 件 的 权 限, 如 只 读'r'或 读 写'wr'等。 

例 如, 我 们 打 开 一 个 数 据 库 更 新 数 据: RandomAccessFile myRAFile; myRAFile = new
RandomAccessFile("/usr/db/stock.dbf","rw"); 

                                       9.13.2 访 问 信 息

RandomAccessFile对 象 的 读 写 操 作 和DataInput/DataOutput对 象 的 操 作 方 式 一 样。 你 可 以 使 用
在DataInputStream 和DataOutputStream里 出 现 的 所 有read()和write()函 数。 

还 有 几 个 函 数 帮 助 你 在 文 件 里 移 动 指 针: l long getFilePointer(); 返 回 当 前 指 针 l void seek(long pos); 将 文
件 指 针 定 位 到 一 个 绝 对 地 址。 地 址 是 相 对 于 文 件 头 的 偏 移 量。 地 址0表 示 文 件 的 开 头。 l long
length(); 返 回 文 件 的 长 度。 地 址"length()"表 示 文 件 的 结 尾。 

                                       9.13.3 增 加 信 息 

你 可 以 使 用 随 机 访 问 文 件 来 设 置 成 增 加 信 息 模 式: myRAFile = new RandomAccessFile("/tmp/java.log","rw");
myRAFile.seek(myRAFile.length()); //Any subsequent write()s will be appended to the file 

9.13.4 追 加 信 息 例 子 下 面 是 一 个 在 已 存 在 文 件 后 面 追 加 字 符 串 的 例 子: import java.io.IOException;
import java.io.RandomAccessFile; 

class raTest { public static void main(String args[]) throws IOException { RandomAccessFile myFAFile; String s = "Information
to Append\nHi mom!\n"; //open our random access file myRAFile = new RandomAccessFile("/tmp/java.log","rw"); //move to the
end of the file myRAFile.seek(myRAFile.length()); //Start appending! myRAFile.writeBytes(s); 

myRAFile.close(); } } 

                                         本 章 小 结 

1. Java通 过 系 统 类 达 到 访 问 标 准 输 入 输 出 的 功 能。 2. 你 可 以 创 建、 读、 写 文 件。 


--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.118.243.11]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.552毫秒