Download presentation
Presentation is loading. Please wait.
1
第七章 输入/输出 标准输入输出 流式I/O基础 文件 随机存取文件 对象输入/输出流
2
输入输出方法 System类管理标准输入输出流和错误流 System.out: 把输出送到缺省的显示(通常是显示器) System.in
从标准输入获取输入(通常是键盘) System.err 把错误信息送到缺省的显示 每当main方法被执行时,就自动生成上述三个对象
3
例子 import java.io.*; public class ReadHello {
public static void main(String args[]) { char inChar; System.out.println("Enter a character:"); try{ inChar=(char)System.in.read(); System.out.println(" "+ inChar); }catch(IOException e) { System.out.println("Error reading from user"); }
4
可处理任何类型数据的输入 BufferedReader in =
new BufferedReader(new InputStreamReader (System.in)) ; String input; try { input = in.readLine() ; } catch (IOException e) { } 详细例子可查看例子KeyboardInput类
5
流Stream的概念 Input stream(输入流), Output stream(输出流)
流是从源到目的的字节的有序序列,先进先出。 两种基本流: Input stream(输入流), Output stream(输出流)
6
流操作的过程 Reading: Writing : open a stream open a stream
while more information read information close the stream Writing : open a stream while more information write information close the stream
7
两种结构的流 Java中实现流式I/O的类都在java.io包中,这些类根据流相对于程序的另一个端点的不同,分为节点流(NodeStream)和过滤流(FilterSteam) 节点流:从特定源如磁盘文件或内存某区域进行读或写入。 过滤流:使用其它的流作为输入源或输出目的地。
8
两种流类的体系 字节流:流中的数据以8位字节为单位进行读写,以InputStream和OutputStream为基础类;
流式I/O类根据操作的数据类型(16位字符或字节)分成两个层次体系。 字节流:流中的数据以8位字节为单位进行读写,以InputStream和OutputStream为基础类; 字符流:流中的数据以16位字节为单位进行读写,以Reader和Writer为基础类。
9
字节流——输入流类层次
10
InputStream 方法 int read() //读一个字节返回
int read(byte[ ] ) // 将数据读入byte[], 返回读的字节数 int read( byte[], int offset, int length ) 其它方法 void close( ) //关闭流。自顶向下关闭Filter stream int available() //返回未读的字节数 long skip(long n) // 跳过n个字节 boolean markSupported( ) //测试打开的流是否支持书签 void mark(int) //标记当前流,并建立int大小缓冲区 void reset( ) // 返回标签出
11
字节流——输出流类层次
12
OutputStream方法 void write( int ) // 写一个字节
void write(byte[ ]) // 写一个字节数组 void write(byte[ ], int offset, int length ) 其它方法 void close( ) void flush( ) // 强行写
13
字符流 Reader和Writer是字符流的两个抽象超类。 Reader和Writer 类实现字节和字符间的自动转换。
14
Reader的类层次
15
Reader的基本方法 int read();//读单个字符 int read(char cbuf[]);//读字符放入数组中
int read(char cbuf[], int offset, int length); //读字符放入数组的指定位置 void close( ) //关闭流。 long skip(long n) // 跳过n个字符 boolean markSupported( ) //测试打开的流是否支持书签 void mark(int) //标记当前流,并建立int大小缓冲区 void reset( ) // 返回标签出 boolean ready() //测试当前流是否准备好进行读
16
Writer的类层次
17
Writer的基本方法 int write(int c) ; // 写单个字符
int write(char cbuf[]) ;// 写字符数组 int write(char cbuf[], int offset, int length) ; int write(String str) ; int write(String str, int offset, int length) ; void close( ) void flush( ) // 强行写
18
字节流与字符流的比较 Reader 和 InputStream以及Writer 与 OutputStream定义的API类似,但操作的数据类型不同。 所有的流——InputStream、 OutputStream 、Reader、 Writer 在创建时自动打开;程序中可以调用close方法关闭流,否则Java运行环境的垃圾收集器将隐含将流关闭。
19
I/O Streams Memory Pipe File Type of I/O Streams Description
CharArrayReader CharArrayWriter ByteArrayInputStream ByteArrayOutputStream 从/向内存数组读写数据. StringReader StringWriter StringBufferInputStream 从/向内存字符串读写数据 Pipe PipedReader PipedWriter PipedInputStream PipedOutputStream 实现管道的输入和输出 File FileReader FileWriter FileInputStream FileOutputStream 统称为文件流。对文件进行读、写操作
20
I/O Streams Object Serialization Data Conversion Printing Buffering
Type of I/O Streams Description Object Serialization ObjectInputStream ObjectOutputStream 对象的输入、输出 Data Conversion DataInputStream DataOutputStream 读、写基本数据类型 Printing PrintWriter PrintStream 包含方便的打印方法 Buffering BufferedReader BufferedWriter BufferedInputStream BufferedOutputStream 在读入或写出时,对数据进行缓存,以减少I/O的次数。
21
Converting between Bytes and Characters
I/O Streams Type of I/O Streams Description Filtering FilterReader FilterWriter FilterInputStream FilterOutputStream 过滤流,在数据进行读或写时进行过滤。 Concatenation SequenceInputStream 把多个输入流连接成一个输入流 Counting LineNumberReader LineNumberInputStream 在读入数据时对行记数 Peeking Ahead PushbackReader PushbackInputStream 通过缓存机制,进行预读 Converting between Bytes and Characters InputStreamReader OutputStreamWriter 按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换。
22
文件流 文件流类包括: FileReader,FileWriter, 创建文件流:常用文件名或File类的对象创建文件流。
FileInputStream,FileOutputStream 创建文件流:常用文件名或File类的对象创建文件流。 例:Copy.java , 利用FileReader,FileWriter, 将farrago.txt的内容拷贝到outagain.txt中。 CopyBytes.java,利用FileInputStream,FileOutputStream。
23
管道流 线程1 连接 线程2 线程3 管道用来把一个线程的输出连接到另一个线程的输入。
PipedReader/PipedInputStream实现管道的输入端; PipedWriter/PipedOutputStream实现管道的输出端。 管道流模型: 管道输入 管道输出 线程1 连接 线程2 线程3
24
管道流的创建 将一个线程的输出流直接挂在另一个线程的输入流, 建立管道,实现线程间数据交换。
PipedInputStream pin= new PipedInputStream( ); PipedOutputStream pout = new PipedOutputStream(pin); PipedOutputStream pout = new PipedOutputStream(); pin.connect(pout);或pout.connect(pin)。
25
管道流示例 Rhymingwords.java,输入一组单词,先将每个单词逆序, 再将所有单词排序,最后将这些单词逆序输出。 程序处理流程:
26
示例中的管道流
27
BufferedInputStream/BufferedOutputStream
是过滤流。 数据从原始流成块读入或将数据积累到一个大数据块后再成批输出。 基本方法: int read() int read( byte[], int offset, int length ) int write(int c) void write(byte[ ], int offset, int length ) BufferedReader增加readLine( ) 方法。
28
DataInputStream/DataOutputStream
DataInputStream和DataOutputStream(Filter stream) 读写基本数据类型: DataInputStream方法 byte readByte( ) boolean readBoolean( ) long readLong( ) char readChar( ) double readDouble( ) float readFloat( ) short readshort( ) int readInt( ) DataOutputStream 方法 void writeByte(byte) void writeBoolean(boolean) void writeLong( long ) void writeChar(char) void writeDouble(double) void writeFloat( float) void writeshort(short) void writeInt ( int) void writeBytes(String) void writeChars(String )
29
示例DataIOTest.java //example of using inputData & outputData
//DataIOTeat.java import java.io.*; public class DataIOTest { 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" };
30
for (int i = 0; i < prices.length; i ++) {
out.writeDouble(prices[i]); out.writeChar('\t'); out.writeInt(units[i]); out.writeChars(descs[i]); out.writeChar('\n'); } out.close(); // read it in again DataInputStream in = new DataInputStream(new FileInputStream("invoice1.txt")); double price; int unit; String desc; double total = 0.0;
31
try { while (true) { price = in.readDouble(); in.readChar(); // throws out the tab unit = in.readInt(); desc = in.readLine(); System.out.println("You've ordered " + unit + " units of " + desc + " at $" + price); total = total + unit * price; } } catch (EOFException e) { System.out.println("For a TOTAL of: $" + total); in.close(); You've ordered 12 units of Java T-shirt at $19.99 You've ordered 8 units of Java Mug at $9.99 You've ordered 13 units of Duke Juggling Dolls at $15.99 You've ordered 29 units of Java Pin at $3.99 You've ordered 50 units of Java Key Chain at $4.99 For a TOTAL of: $892.88
32
文件 其它与文件相关的操作。 File myFile; myFile=new File(“mymotd”);
Java.io.File 文件类提供获取文件基本信息,以及 其它与文件相关的操作。 创建新的文件对象: File myFile; myFile=new File(“mymotd”); myFile = new File(“\”,”mymotd”); …
33
文件I/O操作 为了实现对文件的操作,我们事先建立一个文件的对象 当前目录下打开文件sample.dat
File inFile = new File(“sample.dat”); 当前目录下打开文件sample.dat File inFile = new File(“C:\\SamplePrograms”, “one.txt”); 在目录 C:\SamplePrograms. 下打开文件one.txt 在目录 C:\SamplePrograms. 下打开文件test.dat File inFile = new File (“C:/SamplePrograms/test.dat”);
34
文件的一些方法 判断该文件是否存在 判断该文件是否为真正的文件 if ( inFile.exists( ) ) { … }
if ( inFile.isFile( ) ) { … } File folder = new File(“C:/JavaProjects/Ch11”); String filename[ ] = folder.list( ); for (int i=0; i < filename.length; i++ ){ outputBox.printLine( filename[i] ); } 列出目录 C:\JavaProjects\Ch11下所有的文件名
35
文件的其它操作 使用文件类获取文件的路径信息 设f是一个文件对象
File f=new File(“chapter07”, “temp.dat”); f.exists():返回文件是否存在的boolean值 f.getName():返回文件名temp.dat f.getParent():返回文件所在目录名chapter07 f.getPath():返回文件路径chapter07\temp.dat f.getAbsolutePath():返回绝对路 E:\Java\Test\chapter07\temp.dat
36
文件测试与实用方法 String getName( ) String getPath( )
文件名 String getName( ) String getPath( ) String getAbsolutePath( ) String getParent( ) boolean renameTo( File newName) 文件测试 boolean exists( ) boolean canWrite( ) boolean canRead( ) boolean isFile( ) boolean isDirectory( ) boolean isAbsolute( )
37
File的测试和实用工具
38
文件的其它操作例子 例: 获取当前目录下所有文件名和文件的尺寸: import java.io.*;
public class File_Size{ public static void main(String args[]){ File files=new File("."); //File files=new File("E:\\Java\\Test\\"); String file_list[]=files.list(); for(int i=0;i<file_list.length;i++){ File current_file=new File(file_list[i]); System.out.println(file_list[i]+":"+current_file.length()); }
39
随机存取文件 例:从zip文件中读取特定文件
40
随机存取文件类-RandomAccessFile
“r”,”w”,”rw” 创建随机存取文件: myRAFile = new RandomAccessFile(String name, String mode); myRAFile = new RandomAccessFile(File file, String mode); 常用的方法: 数据读写方法; long getFilePointer( ); //返回当前文件指针 void seek( long pos ); // 文件指针定位到指定位置 long length( ); // 返回文件长度
41
对象输入/输出流 Public class MyClass implements Serializable {
把对象保存到外存,称为永久化。 实现java.io.Serializable接口类的对象可以被输入/输出。 只有对象的数据被保存,方法与构造函数不被保存。 以transient关键字标记的数据不被保存。 Public class MyClass implements Serializable { public transient Thread myThread ; Private transient String customerID; private int total; … }
42
输出对象 在java.util中, 实现了Serialization接口 Public class SerializeDate {
Date d = new Date( ); try { FileOutputStream f = new FileOutputStream(“date.ser”); ObjectOutputStream s= new ObjectOutputStream(f); s.writeObject(d); f.close( ); }catch( IOException e){ e.printStackTrace( ); } public static void main(String args[]){ SerializeDate b = new SerializeDate();}
43
输入对象 Public class UnSerializeDate{ UnSerializeDate(){ Date d = null ;
try { FileInputStream f = new FileInputStream(“date.ser”); ObjectInputStream s = new ObjectInputStream(f); d = (Date) s.readObject(); f.close(); }catch(Exception e){ e.printStackTrace() ;} } public static void main(String args[]){ UnSerializeDate a =new UnSerializeDate();
44
总结1:常用的文件操作类 ——字节输入输出流
总结1:常用的文件操作类 ——字节输入输出流 字节输入输出流 InputStream/OutputStream 方法有read,skip,close/write/flush/close等 利用InputStream/OutputStream继承的类FileInputStream/FileOutputStream来读写文件 FilterInputStream是所有过滤输入流类的父类。在这个类中,重写了InputStream类中的全部成员方法,增加了读取数据的能力.其中DataInputStream能直接从输入流中读取基本数据类型和String类对象的数据。
45
利用FileInputStream来读文件
import java.io.*; public class ReadFile{ public static void main(String[]args){ byte[] info=new byte[12]; String dirName="E:\\Java\\io\\"; String fileName="test"; try{ File fileObject=new File(dirName,fileName); FileInputStream inputFile=new FileInputStream(fileObject); inputFile.read(info); inputFile.close(); } catch(IOException e){ System.out.println("IOException "+e + " occured. "); for(int i=0;i<info.length;i++){ System.out.println(info[i]+ " ");
46
利用DataInputStream来读文件
import java.io.*; public class TryDataInputStream{ public static void main(String[]args){ String dirName=“E:\\Java\\io\\"; String fileName="test"; try{ File fileObject=new File(dirName,fileName); DataInputStream myStream=new DataInputStream(new FileInputStream(fileObject)); String str=myStream.readLine(); while(str!=null){ System.out.println(str); str=myStream.readLine(); } catch(IOException e){ System.out.println("IOException "+e + " occured. ");
47
java 中的unicode 问题: 如果字符流不是来自本地,有可能编码不一样,直接读取会读出不正确字符 处理方法:
BufferedReader reader=new BufferedReader(new InputStreamReader(myStream));
48
利用FileOutputSream写入文件
import java.io.*; public class TryWriteFile{ public static void main(String[]args){ byte[] info={12,34,56}; String dirName=" E:\\Java\\io\\"; String fileName="testWrite"; try{ File dirObject=new File(dirName); if(!dirObject.exists()) dirObject.mkdir(); File fileObject=new File(dirObject,fileName); fileObject.createNewFile(); FileOutputStream outputFile=new FileOutputStream(fileObject); for(int i=0;i<info.length;i++){ outputFile.write(info[i]); } outputFile.close(); catch(IOException e){ System.out.println("IOException "+e + " occured. ");
49
总结2:常用文件操作类 ——字符输入输出流 字符输出流Writer:是一个抽象类,它是所有以字符为单位的输出流的父类。
总结2:常用文件操作类 ——字符输入输出流 字符输出流Writer:是一个抽象类,它是所有以字符为单位的输出流的父类。 Writer的子类有PipedWriter,BufferedWriter,FilteredWriter,StringWriter,CharArrayWriter,OutputStreamWriter,PrintWriter等 字符输入流Reader:是一个抽象类,它是所有以字符为单位的输入流的父类。 Reader的子类有PipedReader,BufferedReader,FilteredReader,StringReader,CharArrayReader,OutputStreamReader,PrintReader等
50
用BufferReader读文件 import java.io.*; public class TryBufferReader{
public static void main(String[]args){ String dirName="E:\\Java\\io\\"; String fileName="test"; try { BufferedReader br = new BufferedReader(new FileReader(fileName)); String line = br.readLine(); //StringBuffer buf = new StringBuffer(); while(line!=null){ System.out.println(line); //buf.append(line); line = br.readLine(); } br.close(); //System.out.println(buf.toString()); } catch (Exception ex) { ex.printStackTrace();
51
用PrintWriter写文件 import java.io.*; public class TryPrintWriter{
public static void main(String[]args){ String dirName=" E:\\Java\\io\\"; String writeFileName="testPrintWriter"; String readFileName="test"; try { BufferedReader br = new BufferedReader(new FileReader(dirName+readFileName)); String line = br.readLine(); File writeFile = new File(dirName,writeFileName); if(!writeFile.exists()) writeFile.createNewFile(); PrintWriter out = new PrintWriter(new FileWriter(writeFile)); while(line!=null){ System.out.println(line); out.println(line); line = br.readLine(); } br.close(); out.close(); catch (Exception ex) { ex.printStackTrace();
52
作业 (1)创建程序从标准输入读入文本,在每行前加入行号后写入文件中。文件名用命令行参数指定。
(2)编写一个程序,读入一个文件,统计指定的某个单词在此文件中出现的次数。 (3)编写一个程序,统计给定文件中包含的每个单词出现的频率,并按单词表的顺序显示统计结果。
53
作业 3、编写一个文件操作类FileOperate,实现以下方法:
(1)创建指定的目录makeDirectory:如果指定的目录的父目录不存在则创建其目录树上所有需要的父目录。 (2) 清空指定目录中的所有文件emptyDirectory方法: 这个方法将尽可能删除所有的文件,但是只要有一个文件没有被删除都会返回false。 (3) listAll方法:列出目录中的所有内容,包括其子目录中的内容。 (4)getTypePart方法:得到指定目录下所有以某后缀命名的所有文件名。 (5)搜索文件SearchFile方法:搜索给定目录下的指定文件,支持模糊查询和深度搜索。如:test.*,则返回所有以test.开头的文件名。 (6)拷贝文件Copy方法:参数1:fromFileName 源文件名;参数2:toFileName 目标文件名;参数3: override 目标文件存在时是否覆盖,返回类型为boolean。
Similar presentations