第六章 i/o 流和系统类

55
Chapter 6 I/O Stream 1 第第第 I/O 第第第 • I/O 第第第第第第 第第第第第 – 第第第第第第第第第 – 第第第第第第第第 – 第第第第第第第第第第 – 第第第第第第第第第第第 • 第第第第第第 I/O 第第第 – C: 第第第第第第第 第第第第第第 , 第第第第第 – C++: 第第第 stream( 第 ) 第第第第 , 第第第第 , 第第第第 – Java: 第第 C++, 第第第 stream 第第第第 Java I/O – 第第第 (System) console I/O – 第第 java.io 第

Upload: onofre

Post on 20-Jan-2016

79 views

Category:

Documents


2 download

DESCRIPTION

第六章 I/O 流和系统类. I/O 是应用程序的一个基本功能 从终端设备读写数据 从文件中读写数据 从网络连接中读写数据 数据读写时的格式化处理 不同的语言对 I/O 的支持 C:  以库的形式提供,功能强大灵活 , 但安全性差 C++: 建立在 stream( 流 ) 概念之上 , 类型安全 , 扩展性好 Java: 类似 C++, 建立在 stream 的概念上 Java I/O 通过系统类 ( System) console I/O 通过 java.io 包. 6.1 Java 的输入 / 输出 stream - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 1

第六章 I/O 流和系统类• I/O 是应用程序的一个基本功能

– 从终端设备读写数据– 从文件中读写数据– 从网络连接中读写数据– 数据读写时的格式化处理

• 不同的语言对 I/O 的支持– C:  以库的形式提供,功能强大灵活 , 但安全性差– C++: 建立在 stream( 流 ) 概念之上 , 类型安全 , 扩展性好– Java: 类似 C++, 建立在 stream 的概念上

• Java I/O– 通过系统类 (System) console I/O– 通过 java.io 包

Page 2: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 2

6.1 Java 的输入 / 输出 stream • I/O stream 的基本概念

Page 3: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 3

• I/O stream 的使用方法

• java.io 包提供了一组类支持上述方法的 I/O stream 的使用(browse the java.io doc.)

• 需要在程序中 import java.io.* 去使用 I/O stream• I/O stream 分为字符 stream 和字节 stream

Page 4: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 4

6.1.1 Java I/O stream 的类层次结构

• 字符 stream 提供 unicode (16 bit) 字符的 I/O• Reader/Writer 是字符 stream I/O 的抽象类 , 提供字符 stream

I/O 的公共 API• 字符 stream 的类层次结构

Page 5: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 5

Page 6: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 6

• 字节 stream 提供 8 bit 字节的 I/O• InputSteam / OutputStream 是字节 stream I/O 的抽

象类 , 提供字节 stream I/O 的公共 API

Page 7: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 7

Page 8: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 8

• Reader / InputStream 定义了类似的 API– Reader’s API

• int read() • int read(char cbuf[])• int read(char cbuf[], int offset, int length)

– InputStream’s API• int read() • int read(byte cbuf[])• int read(byte cbuf[], int offset, int length)

Page 9: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 9

• Writer / OutputStream 定义了类似的 API– Writer’s API

• int write(int c) • int write(char cbuf[]) • int write(char cbuf[], int offset, int length)

– OutputStream’s API• int write(int c) • int write(byte cbuf[]) • int write(byte cbuf[], int offset, int length)

Page 10: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 10

• Decorator Pattern used in the Java file system– The use of layered objects to dynamically and

transparently add responsibilities to individual objects is referred to as the Decorator pattern

– The decorator pattern specifies that all objects that wrap around your initial object have the same interface. This makes the basic use of the decorators transparent—you send the same message to an object whether it has been decorated or not

– Decorators are often used when simple subclassing results in a large number of classes in order to satisfy every possible combination that is needed—so many classes that it becomes impractical

Page 11: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 11

– The Java I/O library requires many different combinations of features, and this is the justification for using the decorator pattern

– The classes that provide the decorator interface to control a particular InputStream or OutputStream are the FilterInputStream and FilterOutputStream

– Ex. Common used decorators• DataInputStream • BufferedInputStream

Page 12: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 12

6.1.2 简单的字节 I/O stream

• 简单的字节 I/O stream 是 InputStream 和 OutputStream 的直接子类

– FileInputSteam / FileOutputStream

– PipedInputStream / PipedOutputStream

– ByteArrayInputStream / ByteArrayOutputStream

– SequenceInputStream

– StringBufferInputStream

1. 读写文件 (JB demo)

Page 13: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 13

例 :import java.io.*;

public class FileStreamsTest {

public static void main(String[] args) throws IOException {

FileInputStream in = new FileInputStream("test_in.txt");

FileOutputStream out = new FileOutputStream("test_out.txt");

int b;

while ((b = in.read()) != -1)

out.write(b);

in.close();

out.close();

}

}

Page 14: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 14

例 : 利用 FileReader / FileWriter 类实现前面例子同样的功能 (JB demo)

import java.io.*;public class Copy { public static void main(String[] args) throws IOException {

File inputFile = new File(" test_in.txt "); File outputFile = new File(" test_out.txt ");

FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c;

while ((c = in.read()) != -1) out.write(c);

in.close(); out.close(); }}

Page 15: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 15

2. 管道流 , pipe streams• pipe streams 可将一个线程 (Thread) 的输出送到另一个线程的输入 ,

不需要另外的中间文件或缓冲区

Page 16: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 16

Page 17: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 17

例 (JB demo, partial):

import java.io.*;

public class RhymingWords {

public static void main(String[] args) throws IOException {

FileReader words = new FileReader("words.txt");

// do the reversing and sorting

Reader rhymedWords = reverse( sort( reverse(words) ) );

// write new list to standard out

BufferedReader in = new BufferedReader(rhymedWords);

String input;

while ((input = in.readLine()) != null)

System.out.println(input);

in.close();

}

Page 18: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 18

public static Reader reverse(Reader source) throws IOException {

BufferedReader in = new BufferedReader(source);

PipedWriter pipeOut = new PipedWriter();

PipedReader pipeIn = new PipedReader(pipeOut);

PrintWriter out = new PrintWriter(pipeOut);

new ReverseThread(out, in).start();

return pipeIn;

}

Page 19: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 19

public static Reader sort(Reader source) throws IOException {

BufferedReader in = new BufferedReader(source);

PipedWriter pipeOut = new PipedWriter();

PipedReader pipeIn = new PipedReader(pipeOut);

PrintWriter out = new PrintWriter(pipeOut);

new SortThread(out, in).start();

return pipeIn;

}

}

Page 20: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 20

3. 存储器读写• Java 提供了 ByteArrayInputStream, 和

ByteArrayOutputStream 用来将数据写入一个在 ByteArrayOutputStream 内部的存储器区域 , 或将数据从一个 ByteArrayInputStream 内部的存储器区域读出

• 访问 ByteArrayInputStream, 和 ByteArrayOutputStream 的方法和访问其它 stream 的方法一样

• StringReader 和 StringWriter 提供类似的功能 , 只不过数据是写入一个字符串 , 或从一个字符串中读出

4. 用 Stream 来连接文件• SequenceInputStream 支持用一个 Stream 从多个输入源连续

读取数据

Page 21: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 21

import java.io.*;

public class Concatenate {

public static void main(String[] args) throws IOException {

ListOfFiles mylist = new ListOfFiles(args);

SequenceInputStream s = new SequenceInputStream(mylist);

int c;

while ((c = s.read()) != -1)

System.out.write(c); s.close();

}

}

Page 22: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 22

6.1.3 过滤流 (filter stream)• Filter stream 一般总是和另一个 stream 结合起来使

用 . Filter stream 从那个 stream 读或向那个 stream 写数据 , 并对读出的或要写入的数据进行处理 ( 过滤 )

• 常见的过滤有– 对数据进行缓冲– 对数据进行计数– 转换数据格式

例 :• DataInputStream and DataOutputStream • BufferedInputStream and BufferedOutputStream • PushbackInputStream • PrintStream (This is an output stream.)

Page 23: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 23

例 :BufferedReader d =

new BufferedReader(new DataInputStream(System.in));String input; while ((input = d.readLine()) != null) { ... //do something interesting here}

Page 24: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 24

1. DataInputStrem 和 DataOutputStream

import java.io.*; // JB demo

public class DataIODemo {

public static void main(String[] args) throws IOException {

// write the data out

DataOutputStream out =

new DataOutputStream(new FileOutputStream("invoice1.txt"));

double[ ] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };

int[ ] units = { 12, 8, 13, 29, 50 };

String[ ] descs =

{

"Java T-shirt", "Java Mug", "Duke Juggling Dolls",

"Java Pin", "Java Key Chain"

};

Page 25: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 25

for(int i = 0; i < prices.length; i ++) { out.writeDouble(prices[i]); out.writeChar('\t'); out.writeInt(units[i]); out.writeChar('\t'); out.writeChars(descs[i]); out.writeChar('\n'); } out.close(); // flush the data in buffer into the file

// read it in again DataInputStream in = new DataInputStream(new FileInputStream("invoice1.txt")); double price; int unit; StringBuffer desc; double total = 0.0;

Page 26: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 26

try{ while (true){

price = in.readDouble(); in.readChar(); // throws out the tab

unit = in.readInt(); in.readChar(); // throws out the tab char chr; desc = new StringBuffer(20); char lineSep =

System.getProperty("line.separator").charAt(0); while ((chr = in.readChar()) != lineSep) desc.append(chr) ; System.out.println("You've ordered " + unit + " units of " +

desc + " at $" + price); total = total + unit * price;

} // while loop} catch (EOFException e) {

} System.out.println("For a TOTAL of: $" + total); in.close();

} }

Page 27: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 27

2. 用户自己建立新的过滤流• 用户自己建立过滤流的步骤

– 创建一个 FilterInputStream 和 FilterOutputStream 的子类– 置换 read() 和 write() 方法– 置换所需的其它方法– 确保输入流和输出流一起工作

Page 28: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 28

• 用户自己建立过滤流的例子– 例子中用到了四个类和一个接口 ( 除了主类 , 都已在 JAVA

类库中 )• CheckedOutputStream / CheckedInputStream

• Checksum interface

• Adler32 class (calculate CRC-32)

• CheckedIODemo ()

(1) CheckedOutputStream• 构造函数public CheckedOutputStream(OutputStream out, Checksum cksum) {

super(out);

this.cksum = cksum;

}

Page 29: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 29

• 在 CheckedOutputStream 中被置换的函数– write(int i)

– write(byte b[ ])

– write(byte b[ ], int offset, int length)

public void write(int b) throws IOException {

out.write(b);

cksum.update(b);

}

public void write(byte[] b) throws IOException {

out.write(b, 0, b.length);

cksum.update(b, 0, b.length);

}

public void write(byte[] b, int offset, int length) throws IOException {

out.write(b, offset, length);

cksum.update(b, offset, length);

}

Page 30: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 30

(2) CheckedInputStream• 构造函数public CheckedInputStream(InputStream in, Checksum cksum) { super(in); this.cksum = cksum;}• 在 CheckedInputStream 中被置换的函数

– int read()– int read(byte[ ] b)– int read(byte[ ] b, offset, length)

public int read() throws IOException { int b = in.read(); if(b != -1)

cksum.update(b); return b;}

Page 31: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 31

public int read(byte[] b) throws IOException { int len; len = in.read(b, 0, b.length); if (len != -1) { cksum.update(b, 0, b.length); } return len; } public int read(byte[] b, int off, int len) throws IOException { len = in.read(b, off, len); if (len != -1) { cksum.update(b, off, len); } return len; }

• 演示 CheckedOutputStream / CheckedOutputStream 的程序import java.io.*; // JB demoimport java.util.zip.*;public class CheckedIODemo {

Page 32: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 32

public static void main(String[] args) throws IOException { Adler32 inChecker = new Adler32(); Adler32 outChecker = new Adler32();

CheckedInputStream in = null; CheckedOutputStream out = null;

try { in = new CheckedInputStream(

new FileInputStream("farrago.txt"), inChecker); out = new CheckedOutputStream(

new FileOutputStream("outagain.txt"), outChecker); } catch (FileNotFoundException e){

System.err.println("CheckedIODemo: " + e); System.exit(-1);

} catch (IOException e) { System.err.println("CheckedIODemo: " + e); System.exit(-1);

}

Page 33: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 33

int c;

while ((c = in.read()) != -1)

out.write(c);

System.out.println("Input stream check sum: " +

inChecker.getValue());

System.out.println("Output stream check sum: " +

outChecker.getValue());

in.close();

out.close();

}

}

• CheckedIODemo 运行后的输出结果Input stream check sum: 736868089

Output stream check sum: 736868089

6.1.4 随机访问文件• 前面所述字符 / 字节都是顺序访问的流

Page 34: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 34

• java.io 中提供了 RandomAccessFile 类• RandomAccessFile 类支持 ( 同时 ) 读和写的操作• RandomAccessFile 提供用于随机访问的方法 ( 文件

指针操作 )– skipBytes() - 相对移位– seek() - 绝对移位– getFilePointer() - 得到当前文件指针位置

• 使用 RandomAccessFile– new RandomAccessFile(“farrago.txt”, “r”); // 只读– new RandomAccessFile(“farrago.txt”, “rw”); // 同时读写写

• RandomAccessFile 支持的典型写操作– write(int i)– write(byte b[ ])– write(byte b[ ], int offset, int length)

Page 35: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 35

• RandomAccessFile 支持的典型读操作– read(int i)

– read(byte b[ ])

– read(byte b[ ], int offset, int length)

• RandomAccessFile 支持的其余读写操作请见 JDK 文档资料6.2 系统类• Java 用系统类提供独立于系统具体实现的统一系统服务接口

Page 36: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 36

• 系统类 (System) 主要包含– 标准输入 , 输出 , 和错误流– 系统属性– 垃圾收集– 动态库的装载

• 系统类的特点– 是一个最终类– 所有的成员变量都是私有的– 所有的变量和方法都是类变量和类方法 ( 可通过类名直接使用 )

例 (JB demo):class UserNameTest {

public static void main(String[] args) {

String name;

name = System.getProperty("user.name");

System.out.println(name);

}

}

Page 37: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 37

6.2.1 标准输入 / 输出• 标准输入 : System.in - 数据来自键盘

– read()

• 标准输出 : System.out - 数据送往显示器– println(x) // print x and a newline

– print(x) // print x only

• 错误输出 : System.err - 数据送往显示器• print/println 只接受一个参数 , 但参数可以是下述之一

– Object // means the parameter can be any class

– String

– char[]

– int

– long

– float

– double

– boolean

Page 38: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 38

例 (JB demo):

public class DataTypePrintTest {

public static void main(String[ ] args) {

Thread objectData = new Thread();

String stringData = "Java Mania";

char[] charArrayData = { 'a', 'b', 'c' };

int integerData = 4;

long longData = Long.MIN_VALUE;

float floatData = Float.MAX_VALUE;

double doubleData = Math.PI;

boolean booleanData = true;

System.out.println(objectData);

System.out.println(stringData);

System.out.println(charArrayData);

System.out.println(integerData);

System.out.println(longData);

Page 39: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 39

System.out.println(floatData);

System.out.println(doubleData);

System.out.println(booleanData);

}

}

• 程序运行输出Thread[Thread-4,5,main]

Java Mania

abc

4

-9223372036854775808

3.40282e+38

3.14159

true

6.2.2 系统属性• 系统类维护一个由 < 关键字 , 值 > 对描述的系统属性的集合

Page 40: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 40

Page 41: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 41

1. 系统属性的获取– System.getProperty(“path.separator”); // may return null– // getProperty with default return value

System.getProperty("subliminal.message", "Buy Java Now!");– System.getProperties(); // return a Properties object

2. 系统属性的设置• 可通过 System.setProperties() 修改当前的系统属性

Page 42: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 42

import java.io.*; // JB demo

import java.util.Properties;

public class PropertiesTest {

public static void main(String[] args) throws Exception {

// set up new properties object from file "myProperties.txt"

FileInputStream propFile = new

FileInputStream( "myProperties.txt");

Properties p = new Properties(System.getProperties());

p.load(propFile);

// set the system properties

System.setProperties(p); // display new properties

System.getProperties().list(System.out);

}

}• myProperties.txt: subliminal.message=Buy Java Now!

Page 43: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 43

-- listing properties --

java.runtime.name=Java(TM) 2 Runtime Environment, Stand...

sun.boot.library.path=C:\JBuilder6\jdk1.3.1\jre\bin

java.vm.version=1.3.1-b24

java.vm.vendor=Sun Microsystems Inc.

java.vendor.url=http://java.sun.com/

Page 44: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 44

path.separator=;

java.vm.name=Java HotSpot(TM) Client VM

file.encoding.pkg=sun.io

java.vm.specification.name=Java Virtual Machine Specification

user.dir=D:\MSE_JBuilder\PropertiesTest

java.runtime.version=1.3.1-b24

Page 45: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 45

java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment

os.arch=x86

java.io.tmpdir=C:\DOCUME~1\WINDOW~1\LOCALS~1\Temp\

line.separator= java.vm.specification.vendor=Sun Microsystems Inc.

java.awt.fonts= os.name=Windows 2000

subliminal.message=Buy Java Now!

java.library.path=C:\JBuilder6\jdk1.3.1\bin;.;C:\WINDOW...

java.specification.name=Java Platform API Specification

java.class.version=47.0

os.version=5.1

Page 46: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 46

user.home=C:\Documents and Settings\Windows XP

user.timezone= java.awt.printerjob=sun.awt.windows.WPrinterJob

file.encoding=GBK

java.specification.version=1.3

user.name=Windows XP

java.class.path=D:\MSE_JBuilder\PropertiesTest\classe...

java.vm.specification.version=1.0

java.home=C:\JBuilder6\jdk1.3.1\jre

user.language=zh

java.specification.vendor=Sun Microsystems Inc.

awt.toolkit=sun.awt.windows.WToolkit

Page 47: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 47

java.version=1.3.1

java.ext.dirs=C:\JBuilder6\jdk1.3.1\jre\lib\ext

sun.boot.class.path=C:\JBuilder6\jdk1.3.1\jre\lib\rt.jar;...

java.vendor=Sun Microsystems Inc.

file.separator=\

java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...

sun.cpu.endian=little

sun.io.unicode.encoding=UnicodeLittle

user.region=CN

sun.cpu.isalist=pentium i486 i386

Page 48: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 48

6.2.3 集成原始方法 (native method)• 原始方法 : 由其它程序语言实现的 Java 方法

Page 49: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 49

• 从 C 语言中调用 JAVA 语言编写的代码

Page 50: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 50

Page 51: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 51

Page 52: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 52

The Circumstance to Use JNI1. The standard Java class library may not support the

platform-dependent features needed by your application2. You may already have a library or application written in

another programming language and you wish to make it accessible to Java applications

3. You may want to implement a small portion of time-critical code in a lower-level programming language, such as assembly, and then have your Java application call these functions.

“The JNI is for programmers who must take advantage of platform-specific functionality outside of the Java Virtual Machine. Because of this, it is recommended that only experienced programmers should attempt to write native methods or use the Invocation API! “

Page 53: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 53

6.2.4 其它系统方法1. 获取系统时间• System.currentTimeMIlis(); // return long (64 bits)

– Returns the current time in milliseconds (the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC)

2. 数组拷贝• public static void arraycopy(Object src, int src_position, Object dst,

int dst_position, int length)

Page 54: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 54

public class ArrayCopyDemo { // JB demo

public static void main(String[] args) {

char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' };

char[] copyTo = new char[7];

System.arraycopy(copyFrom, 2, copyTo, 0, 7);

System.out.println(new String(copyTo));

}

}

Page 55: 第六章  I/O  流和系统类

Chapter 6 I/O Stream 55

3. 退出运行系统• void exit(int status)• 退出 Java 解释器 , • 用户可传递一个整型的退出代码给 exit() 方法 , 用以说明退出

原因• System.exit(n); // n for the reason to exit, non zero means

error

第六章作业 :1. What class would you use to read a few pieces of data that

are at known positions near the end of a large file?

2. Implement a pair of classes, one Reader and one Writer, that count the number of times a particular character, such as e, is read or written. The character can be specified when the stream is created. Write a program to test your classes. You can use the text of this question as the content of the input file