第十章 输入 / 输出处理

47
1 第第第 第第 / 第第第第

Upload: daryl

Post on 18-Jan-2016

88 views

Category:

Documents


9 download

DESCRIPTION

第十章 输入 / 输出处理. 输入输出概述. 输入 / 输出处理: 从键盘读取数据; 向屏幕中输出数据; 从文件中读或者向文件中写数据 在一个网络连接上进行读写操作等。 在 Java 中,把这些不同类型的输入、输出抽象为 流 ( Stream ) ,用统一的接口来表示,从而使程序设计简单明了。. 输入流和输出流. 流是程序和外界进行数据交换的通道 输入流 (InputStream) 程序通过输入流从数据源读取数据 输出流 (OutputStream) 通过输出流向目的地写数据。. java.io 包. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第十章 输入 / 输出处理

1

第十章 输入 / 输出处理

Page 2: 第十章 输入 / 输出处理

2

输入输出概述 输入 / 输出处理:

从键盘读取数据; 向屏幕中输出数据; 从文件中读或者向文件中写数据 在一个网络连接上进行读写操作等。

在 Java 中,把这些不同类型的输入、输出抽象为流( Stream ),用统一的接口来表示,从而使程序设计简单明了。

Page 3: 第十章 输入 / 输出处理

3

输入流和输出流 流是程序和外界进行数据交换的通道

输入流 (InputStream) 程序通过输入流从数据源读取数据

输出流 (OutputStream) 通过输出流向目的地写数据。

Page 4: 第十章 输入 / 输出处理

4

java.io 包

在 Java 开发环境中,主要是由包 java.io 中提供的一系列的类和接口来实现输入 / 输出处理。

标准输入 / 输出 (System.out 和 System.in)处理则是由包 java.lang 中提供的类来处理的,但这些类又都是从包 java.io 中的类继承而来。

Page 5: 第十章 输入 / 输出处理

5

字节流和字符流

输入输出流的类型 字节输入 / 输出流:以字节为读写单位 字符输入 / 输出流:以字符为读写单位

Page 6: 第十章 输入 / 输出处理

6

字节流

InputStream ByteArrayInputStream FileInputStream FilterInputStream

BufferedInputStream DataInputStream PushbackInputStream

ObjectInputStream PipedInputStream SequenceInputStream

OutputStream ByteArrayOutputStream FileOutputStream FilterOutputStream

BufferedOutputStream DataOutputStream PrintStream

ObjectOutputStream PipedOutputStream

InputStream 类是所有字节输入流的父类 OutputStream 类是所有字节输出流的父类

Page 7: 第十章 输入 / 输出处理

7

InputStream 类的方法 (1) InputStream 是一个抽象类,不能被实例化。它提供了一系列

和读取数据有关的方法。 int read() // 从数据源读入一个字节的数据,当读到流的末尾时,返回 -1 int read(byte[ ] b)

// 从输入流中读取若干个字节到字节数组 b ,返回值为实际读取的字节数,当读到流的末尾时,返回 -1

int read(byte[ ] b,int off, int len)// 从输入流中读取长度为 len 的数据,写入数组 b 中从索引 off 开始的位置,并返回读取得字节数。当读到流的末尾时,返回 -1

void close()// 当完成读操作后,应该关闭输入流。

Page 8: 第十章 输入 / 输出处理

8

InputStream 类的方法 (2) skip() :跳过流中若干字节数

available() :返回流中可用字节数

mark() :在流中标记一个位置

reset() :返回标记过得位置

markSupport() :是否支持标记和复位操作

Page 9: 第十章 输入 / 输出处理

9

OutputStream 类的方法 OutputStream 类是所有字节输出流的父类,它是一个抽象类,不能被实例化。

它提供了一系列和写数据有关的方法。

void write(int), // 向输出流写一个字节数据。 void write(byte[] b) // 向输出流写一个字节数组的数据

void close() // 当完成写操作后,应该关闭输出流。

void flush() OutputStream 类本身的 flush() 方法不执行任何操作,它的一些带有缓冲区的子

类(比如 BufferedOutputStream 和 PrintStream 类)覆盖了 flush() 方法。通过带缓冲区的输出流写数据时,数据先保存在缓冲区中,积累到一定程度才会真正写到输出流中。缓冲区通常用字节数组实现,实际上是指一块内存空间。 flush() 方法强制把缓冲区内的数据写到输出流中。

Page 10: 第十章 输入 / 输出处理

10

InputStream 和 OutputStream 示例 把输入流中的所有内容复制到输出流中

public void copy(InputStream in, OutputStream out) throws IOException {

byte[] buf = new byte[4096]; int len = in.read(buf); //read 方法可能抛出 IOException while (len != -1) { out.write(buf, 0, len); //write 方法可能抛出 IOException len = in.read(buf); }}

Page 11: 第十章 输入 / 输出处理

11

字节流——文件流 FileInputStream 类:

用来打开一个输入文件,若要打开的文件不存在,则会产生 FileNotFoundException 异常,这是一个已检查异常,必须捕获或抛出;

FileOutputStream 类: 用来打开一个输出文件,若要打开的文件不存在,则会创建

一个新的文件,否则原文件的内容会被新写入的内容所覆盖。

在进行文件的读 / 写操作时,可能会产生已检查异常 IOException ,必须捕获或抛出(其它的输入 / 输出流处理时也同样需要进行输入 / 输出异常处理)。

Page 12: 第十章 输入 / 输出处理

12

文件字节流的构造方法 文件流的构造方法:

FileInputStream(String name) 打开一个文件路径名为 name 的文件作为输入。

FileOutputStream(String name) 创建一个文件路径名为 name 的文件作为输出,文件如果

已经存在,则其内容被清空。

FileOutputStream(String name, boolean append)

创建一个文件路径名为 name 的文件作为输出,文件如果已经存在,则在该输出流上输出的内容被接到原有内容之后还是覆盖取决于 append 的值。

Page 13: 第十章 输入 / 输出处理

13

文件流示例 1 把一个文件的内容加到另一个文件后public void cat(String fsrc, String fdest) { try { InputStream in = new FileInputStream(fsrc); OutputStream out =

new FileOutputStream(fdest, true); copy(in, out); out.close(); in.close(); } catch (IOException ex) { System.err.println(ex); }}

Page 14: 第十章 输入 / 输出处理

14

文件流示例 2功能:将文件中的内容显示在控制台。

import java.io.*;

class FileReaderSample { public static void main(String agrs[])throws IOException{ FileInputStream in=new FileInputStream(“e:\\in.txt"); int data; while((data=in.read())!=-1) System.out.print(data +“ ”); // 以 ASCII 码的形式显示文件中的内容 in.close(); }} 演示 FileReaderSample.java

Page 15: 第十章 输入 / 输出处理

15

文件流示例 3功能:将字符串写入文件

import java.io.*;

public class FileWriterSample{

public static void main(String args[]) { try { FileOutputStream fileOut = new FileOutputStream(“E:\\out.tx

t"); fileOut.write(“ 你好” .getBytes()); // 调用 String.getByte() 方法返回字符串数组 fileOut.close(); } catch(FileNotFoundException e) { } catch(IOException e) { } }}

演示 FileWriterSample.java

Page 16: 第十章 输入 / 输出处理

16

字节流—过滤流 FilterInputStream 和 FilterOutputStre

am: 用于扩展字节输入 / 输出流功能的装饰器,它有好几个子类,分别用来扩展字节输入 / 输出流的某一种功能

要使用过滤流,首先必须把它连接到某个输入 / 输出流上,通常在构造方法的参数中指定所要连接的流:

FilterInputStream(InputStream in); FilterOutputStream(OutputStream out);

Page 17: 第十章 输入 / 输出处理

17

过滤流子类: DataInputStream 类 DataInputStream : 用于读取基本类型数据,如 int 、 float 、 long 、 double 和 boolean 等,

以及采用 UTF-8编码的字符串。 DataInputStream 类的所有读方法都都以“ read”开头,比如:

byte readByte() :从输入流中读取 1 个字节,把它转换为 byte 类型的数据。

long readLong() :从输入流中读取 8 个字节,把它转换为 long 类型的数据。

float readFloat() :从输入流中读取 4 个字节,把它转换为 float 类型的数据。

String readUTF() :从输入流中读取 1 到 3 个字节,把它转换为采用 UTF-8编码的字符串。

Page 18: 第十章 输入 / 输出处理

18

过滤流子类: DataOutputStream 类 DataOutputStream :用于写入基本类型数据,如 int 、

float 、 long 、 double 和 boolean 等和 UTF编码的字符串

writeByte() :写入 1 个字节到输出流。

writeLong() :写一个 long 类型的数据到输出流。

writeFloat() :写一个 long 类型的数据到输出流。

writeUTF() :写入一个用 UTF-8编码的字符串。

Page 19: 第十章 输入 / 输出处理

19

DataInputStream 和 DataOutputStream示例

FileOutputStream out1=new FileOutputStream("D:\\test.txt"); BufferedOutputStream out2=new BufferedOutputStream(out1); //装饰文件输出流 DataOutputStream out=new DataOutputStream(out2); //装饰带缓冲输出流 out.writeByte(-12); out.writeLong(12); out.writeChar('1'); out.writeUTF(" 好 "); out.close();

InputStream in1=new FileInputStream("D:\\test.txt"); BufferedInputStream in2=new BufferedInputStream(in1); //装饰文件输入流 DataInputStream in=new DataInputStream(in2); //装饰缓冲输入流 System.out.print(in.readByte()+" "); System.out.print(in.readLong()+" "); System.out.print(in.readChar()+" "); System.out.print(in.readUTF()+" "); in.close();

演示 FormatDataIO.java

Page 20: 第十章 输入 / 输出处理

20

过滤流子类:缓冲流 类 BufferedInputStream 和 BufferedOutputStream

实现了带缓冲的过滤流,它提供了缓冲机制,把任意的 I/O 流“捆绑”到缓冲流上,可以提高读写效率。

在初始化时,除了要指定所连接的输入输出流之外,还可以指定缓冲区的大小。

BufferedInputStream(InputStream in[, int size]) BufferedOutputStream(OutputStream out[, int size])

Page 21: 第十章 输入 / 输出处理

21

过滤流子类:缓冲流示例

public void copy(InputStream in, OutputStream out)

throws IOException { out = new BufferedOutputStream(out, 4096); byte[] buf = new byte[4096]; int len = in.read(buf); while (len != -1) { out.write(buf, 0, len); len = in.read(buf); } out.flush(); // 强制将尚未填满的缓冲区中的数据送出。}

Page 22: 第十章 输入 / 输出处理

22

过滤流:其它

PushBackInputStream :它提供了一个方法将刚刚读入的一个或多个字节退回到输入流中去。

PrintStream :其作用是将 Java语言中的不同类型的数据以字符表示形式输出到相应的输出流中去。

Page 23: 第十章 输入 / 输出处理

23

字节流——标准流语言包 java.lang 中的 System 类管理标准输入 / 输出流

和错误流。

System.in 继承 InputStream , 用于从标准输入设备中获取输入数据 ( 通常是键盘 ) 。

System.out , 继承 PrintStream ,把输出送到缺省的显示设备 ( 通常是控制台 ) 。

System.err , 继承 PrintStream ,把错误信息送到缺省的显示设备 ( 通常是控制台 ) 。

每当 main 方法被执行时,就自动生成上述三个对象。

Page 24: 第十章 输入 / 输出处理

24

标准输入输出示例public static void main(String args[]) { try { byte bArray[]=new byte[128]; String str; System.out.println(“Please enter something:"); System.in.read(bArray); str = new String(bArray); System.out.print("You entered:"); System.out.println(str); } catch(IOException ioe) { System.err.println(ioe.toString()); }}

见 SysIOSample.java

Page 25: 第十章 输入 / 输出处理

25

URL 输入流( java.net.URL ) InputStream is = null; try { URL url= new URL("http://www.javathinker.org/weiqin/sole.ht

m"); is = url.openStream(); byte buffer[] = new byte[2048]; is.read(buffer,0,buffer.length); System.out.println(new String(buffer)); } catch (IOException e){}

演示 URLTest.java

Page 26: 第十章 输入 / 输出处理

26

字符输入输出流 在 JDK1.1之前, java.io 包中的流只有普通的字节流

(以 byte 为基本处理单位的流),这种流对于以 16位的 Unicode码表示的字符流处理很不方便。从 JDK1.1 开始, java.io 包中加入了专门用于字符流处理的类,它们是以 Reader 和Writer 为基础派生的一系列类。

同 InputStream 和 OutputStream 一样, Reader 和Writer也是抽象类,只提供了一系列用于字符流处理的接口。它们的方法与类 InputStream 和 OutputStream 类似,只不过其中的参数换成字符或字符数组。

Page 27: 第十章 输入 / 输出处理

27

Reader 和Writer 类

Reader BufferedReader

LineNumberReader CharArrayReader FilterReader

PushbackReader InputStreamReader

FileReader PipedReader StringReader

Writer BufferedWriter

CharArrayWriter FilterWriter

OutputStreamWriter FileWriter

PipedWriter StringWriter PrintWriter

Reader :是所有字符输入流的父类 Writer : 是所有字符输出流的父类。

Page 28: 第十章 输入 / 输出处理

28

输入输出字符流的构造 默认情况下,如果你构造了一个连接到字符流的 Reader 和Writer ,那么转换规则会对本地平台默认的字符编码和 Unicode 进行转换。

在构造 InputStreamReader 类和 OutputStreamWriter 类的实例时,你可以指定输出流或输入流的字符编码。

InputStreamReader reader=new InputStreamReader(new FileInputStream("D:\\test.txt"), "UTF-8" );char c=(char)reader.read();

Page 29: 第十章 输入 / 输出处理

29

关于字符编码 系统属性file.encoding 表示本地平台的字符编码, ,

中文系统一般是 GBK (参见 propertyTester.java )

字符串的相关方法 String(byte[] bytes, String enc) //按指定的字符编码 enc构造字符串

byte[] getBytes(String enc) // 获得按指定的字符编码的字节数组

Page 30: 第十章 输入 / 输出处理

30

Properties p=System.getProperties(); //Properties 类封装了与 java运行环境相关的系统属性集,在 java.util 包中 Enumeration k=p.keys(); Enumeration e=p.elements();

String userName= (String)p.get("user.name"); while(k.hasMoreElements()){ System.out.println(k.nextElement()+ " :"+ e.nextElement()); }

(参见 propertyTester.java )

如何获得本地平台的编码类型

Page 31: 第十章 输入 / 输出处理

31

字符流——与字节流连用 InputStreamReader OutputStreamWriter

用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。

InputStreamReader(InputStream in); //缺省规范 InputStreamReader(InputStream in, String enc); // 指定规范 enc OutputStreamWriter(OutputStream out); //缺省规范 OutputStreamWriter(OutputStream out, String enc); // 指定规范 e

nc

Page 32: 第十章 输入 / 输出处理

32

字节流与字符流连用示例import java.util.*;import java.io.*;

public class ReadFile{

public static void main(String args[]) throws Exception{ MyReaderWriter rw=new MyReaderWriter(); rw.copyfile(“E:\\hello.txt”,“E:\\hello1.txt"); }

public void copyfile(String from, String to)throws Exception{ char[] cbuf=new char[2064]; FileInputStream fin=new FileInputStream(from); InputStreamReader ir=new InputStreamReader(fin);

FileOutputStream fo=new FileOutputStream(to); OutputStreamWriter ow=new OutputStreamWriter(fo,"MS950");

int length=0; while((length=ir.read(cbuf, 0, 2064))!=-1){ System.out.println(cbuf); } ir.close(); ow.close(); }

演示 ReadFile.java

Page 33: 第十章 输入 / 输出处理

33

BuffereReader和 PrintWriter

BfferedReader

PrintWriter

Page 34: 第十章 输入 / 输出处理

34

BufferedReader

BufferedReader

带有缓冲区,可以先把一批数据读到缓冲区内,接下来的读操作都是从缓冲区内获取数据,避免每次都从数据源读取数据并进行字符编码转换,从而提高读操作的效率。

可采用 BufferedReader 来装饰其他Reader ,以提高效率。 构造方法:

BufferedReader(Reader in) :参数 in 指定被装饰的 Reader 类。 BufferedReader(Reader in, int sz) :参数 in 指定被装饰的 Reader

类,参数 sz指定缓冲区的大小,以字符为单位。 提供了整行字符处理方法:

public String readLine() : BufferedReader 的方法,从输入流中读取一行字符,行结束标志为‘ \n’、‘ \r’或两者一起。

Page 35: 第十章 输入 / 输出处理

35

PrintWriter

PrintWriter 能输出格式化的数据, PrintWriter 的写数据的方法都以 print 开头,比如:

print(int i) :向输出流写入一个 int 类型的数据。 print(long l): 向输出流写入一个 long 类型的数据。 print(float f): 向输出流写入一个 float 类型的数据。 print(String s): 向输出流写入一个 String 类型的数据。 println(int i): 向输出流写入一个 int 类型的数据和换行符。 println(long l): 向输出流写入一个 long 类型的数据和换行符。 println(float f): 向输出流写入一个 float 类型的数据和换行符。 println(String s): 向输出流写入一个 String 类型的数据和换行符

println(“hello”);等价于:print(“hello”)print(“\n”)

Page 36: 第十章 输入 / 输出处理

36

字符流——其它 CharArrayReader & CharArrayWriter

对字符数组进行处理

StringReader & StringWriter 对字符串进行处理

FilterReader & FilterWriter 过滤字符流

PipedReader & PipedWriter 管道字符流

LineNumberReader 行处理字符输入流

Page 37: 第十章 输入 / 输出处理

37

文件类 File :以文件路径名的形式代表一个文件或目录 FileDescriptor :代表一个打开文件的文件描述 FileFilter & FilenameFilter :用于列出满足条件的文

件 File.list(FilenameFilter fnf) File.listFiles(FileFilter ff) FileDialog.setFilenameFilter(FilenameFilter fnf)

FileInputStream & FileReader :顺序读文件 FileOutputStream & FileWriter :顺序写文件 RandomAccessFile :提供对文件的随机访问支持。

Page 38: 第十章 输入 / 输出处理

38

File 类 File 类(在 java.io 包中)提供了若干创建文

和处理文件、目录和获取它们基本信息的方法。

File 类的构造方法:1. File(String pathname)

//pathname 为文件或目录的路径

2. File(String parent, String child)

3. File(File parent, String child)

Page 39: 第十章 输入 / 输出处理

39

File 类的方法 查看文件属性: boolean canRead() boolean isFile() long lastModified() : // 可强制转化为 Date 类型 创建或删除目录: mkdir(), delete() // 若为目录,必须为空目录,才可以删除 列出目录下的所有文件: String[] list() 判断文件是否存在: boolean exists()

重新命名文件: renameTo()

Page 40: 第十章 输入 / 输出处理

40

File 类的方法 创建新文件: createNewFile()

返回文件名或最后一级目录名 String getName()

返回文件所在目录的路径或本目录的上级目录路径 String getParent()

System.out.println("getParent="+new File ("E:\\Dir1\\Dir2\\test.txt").getParent());System.out.println("getName="+new File ("E:\\Dir1\\Dir2\\test.txt").getName());

结果:E:\Dir1\Dir2test.txt

Page 41: 第十章 输入 / 输出处理

41

File dir1=new File("D:\\dir1");if(!dir1.exists())dir1.mkdir();

File dir2=new File(dir1,"dir2");if(!dir2.exists())dir2.mkdirs();

File dir3=new File(dir1,"dir3");if(!dir3.exists())dir3.mkdirs();

File dir4=new File(dir1,"dir3\\dir4");if(!dir4.exists())dir4.mkdirs();

File file=new File(dir2,"test.txt");

if(!file.exists())file.createNewFile();

创建文件系统

创建目录和文件示例

见 UseFile.java

Page 42: 第十章 输入 / 输出处理

42

打印目录和文件示例public static void listDir(File dir){ File[ ] lists=dir.listFiles(); // 打印当前目录下包含的所有子目录和文件的名字 String info=" 目录 :"+dir.getName()+"("; for(int i=0;i<lists.length;i++) info+=lists[i].getName()+" "; info+=")"; System.out.println(info); }

见UseFile.java

Page 43: 第十章 输入 / 输出处理

43

/** 删除目录或文件,如果参数 file代表目录,会删除当前目录以及目录下的所有内容 */ public static void deleteDir(File file){ // 如果file代表文件,就删除该文件 if(file.isFile()){ file.delete(); return; } // 如果file代表目录,先删除目录下的所有子目录和文件 File[] lists=file.listFiles(); for(int i=0;i<lists.length;i++) deleteDir(lists[i]); //递归删除当前目录下的所有子目录和文件 //最后删除当前目录 file.delete(); }

删除目录或文件示例

见UseFile.java

Page 44: 第十章 输入 / 输出处理

44

RandomAccessFile 类

RandomAccessFile 类: 用来随机读取和写入文件 (即可以写入文件中任何一个地方 )

实现了 DataInput 和 DataOutput 接口 readBoolean(), readByte(), readChar(), readLine()… writeBoolean(), writeByte(), writeChar(), writeLine()…

提供了定位文件的方法

Page 45: 第十章 输入 / 输出处理

45

RandomAccessFile(File file, String mode)

RandomAccessFile(String name, String mode)

mode 的取值: “r” 只读 . 任何写操作都将抛出 IOException 。 “rw” 读写 . 文件不存在时会创建该文件,文件存在时,原

文件内容不变,通过写操作改变文件内容。 “rws” 同步读写 . 等同于读写,但是任何协操作的内容都

被直接写入物理文件,包括文件内容和文件属性。 “rwd” 数据同步读写 . 等同于读写,但任何内容写操作都直接写到物理文件。

RandomAccessFile 类的构造方法

Page 46: 第十章 输入 / 输出处理

46

DataInput 和 DataOutput 中的方法 readInt(), writeDouble()…

int skipBytes(int n) :将指针向下移动若干字节

length() :返回文件长度

long getFilePointer() :返回指针当前位置

void seek(long pos) :将指针调到所需位置

void setLength(long newLength) :设定文件长度

RandomAccessFile 类的方法

Page 47: 第十章 输入 / 输出处理

47

import java.io.*;

public class RandomTester { public static void main(String args[])throws IOException{ RandomAccessFile rf=new RandomAccessFile("D:\\test.dat","rw"); for(int i=0;i<10;i++) rf.writeLong(i*1000);

rf.seek(5*8); // 从文件开头开始,跳过第 5 个 long 数据,接下来写第 6 个 long 数据

rf.writeLong(1234);

rf.seek(0); // 把读写指针定位到文件开头 for(int i=0;i<10;i++) System.out.println("Value"+i+":"+rf.readLong());

rf.close(); }

Value0:0Value1:1000Value2:2000Value3:3000Value4:4000Value5:1234Value6:6000Value7:7000Value8:8000Value9:9000

RandomTester.java