第3章 流与Java中的文件操作 孙焘
重点: 1 6 2 7 3 8 4 9 5 10 输入输出方法 文件的其他操作 输入输出流的基类 Java中的Unicode FILE I/O 3 管道流 8 输入输出流 4 对象流 9 随即存取文件 5 流的分类 10
3.1 输入输出方法 数据流是指所有的数据通信通道 在java中有关流的操作使用java.io.* 什么是数据流 ? 文件,字符串 存储区 文件 文件 终点 起点 程序 程序 网络端点 终端 数据流 网络端点 数据流是指所有的数据通信通道 在java中有关流的操作使用java.io.* 出于安全的考虑,小应用不能实现文件I/O流
3.1 输入输出方法 System类管理标准输入输出流和错误流 System.out: 把输出送到缺省的显示(通常是显示器) System.in 从标准输入获取输入(通常是键盘) System.err 把错误信息送到缺省的显示 每当main方法被执行时,就自动生成上述三个对象
3.1 输入输出方法 为什么输入的是字符,输出是乱码? 原因:System.out.println(bArray)输出的是数组的地址而不是字符 改进:将字符数组变换成字符串 原来是:System.out.println(bArray); 现在为:String s=new String(bArray,0); System.out.println(s); System.in是属于BufferedInputStream类型 System.out是属于PrintStream类型 System.err也是属于PrintStream类型
3.2 输入输出流的基类 Java中每一种流的基本功能依赖于基本类InputStream和OutputStream 它们是抽象类,不能直接使用 属于InputStream类的方法有: read():从流中读入数据 skip():跳过流中若干字节数 available():返回流中可用字节数 mark():在流中标记一个位置 reset():返回标记过得位置 markSupport():是否支持标记和复位操作 close():关闭流
3.2 输入输出流的基类 方法read()提供了三种从流中读数据的方法. int read():读一个整数 int read(byte b[]):读多个字节到数组中 int read(byte,int off,int len); 属于OutputStream类的方法有: write(int b):将一个整数输出到流中 write(byte b[]):将数组中的数据输出到流中 write(byte b[], int off,int len):将数组b中从off指定的位置开始len长度的数据输出到流中
3.2 输入输出流的基类 flush():将缓冲区中的数据强制送出 close():关闭流. PrintStream类 println()不属于OutputStream类,它是PrintStream类的子类,能提供复杂的输出 PrintStream类的方法有: write, flush, checkError,print, println,close. 其中println可以输出多种形式的数据.例如: println(String s), println(char c)等
3.3 File I/O 文件对象的建立 File fp=new File(“tempfile.txt”); 对文件操作要定义文件流 FileInputStream类用来打开一个输入文件 FileOutputStream类用来打开一个输出文件 输出文件 输入文件
3.3 File I/O 文件流的建立 FileInputStream in=new FileInputStream(fp); FileOutputStream out=new FileOutputStream(fp); 例:文件拷贝(注意要捕获文件异常) 输入流的参数是用于输入的文件名 输出流的参数是用于输出的文件名 file1.txt file2.txt 输入流 输出流
3.3 File I/O 增加缓冲区流,减少访问硬盘的次数,提高效率 file1.txt 输入缓冲区 输出缓冲区 file2.txt 输入流 输出流 文件 文件流 缓冲区流
3.3 File I/O 缓冲区流: BufferedInputStream和 BufferedOutputStream 将它们与文件流相接 FileInputStream in=new FileInputStream(“file1.txt”); BufferedInputStream bin= new BufferedInputStream(in,256) int len; byte bArray[]=new byte[256]; len=bin.read(bArray); len中得到是长度, bArray中得到的是数据
3.3 File I/O 只有缓冲区满时,才会将数据送到输出流. Java在输出数据流中,当对方尚未将数据取走时,程序就会被阻塞. 有时要人为地将尚未填满的缓冲区中的数据送出,使用flush()方法. 文件
3.4 数据输入输出流 什么时候需要数据输入输出流? 文件流和缓冲区流的处理对象是字节或字节数组,利用数据输入输出流可以实现对文件的不同数据类型的读写. DataInputStream、DataOutputStream 一种较为高级的数据输入输出方式,除了字节和字节数组,还可以处理int,float,boolean等类型. 还可以用readLine方法读取一行信息 可使用的方法: write,writeBoolean…,read,readByte…等
3.4 数据输入输出流 数据流的建立 FileOutputStream fos= new FileOutputStream(”file2.txt")); DataInputStream dis= new DataInputStream(fos) 数据输出流可以是一个已经建立好的输入数据流对象,例如网络的连结,文件等.
3.4 数据输入输出流 DateLine(InputStream in)(计算字符和行数) { DataInputStream data=new DataInputStream(in); String currentLine; int lineCount=0; int charCount=0; while((currentLine=dataIn.readLine())!=null) { ++lineCount; charCount+=currentLine.length(); } return (charCount/(float)lineCount);
3.5 随机存取文件 类RandomAccessFile zip文件需要用随机方法处理 文件目录给出个文件的入口,可以随机读取. 创建一个随机文件 new RandomAccessFile(“file1.txt”, “r”); new RandomAccessFile(“file2.txt”, “rw”); 随机文件可以同时完成读和写操作. 文件目录 zip文件
3.5 随机存取文件 支持随机文件操作的方法: readXXX()或writeXXX() skipBytes();将指针乡下移动若干字节 seek():将指针调到所需位置 getFilePointer():返回指针当前位置 length():返回文件长度 利用seek(long pos)方法查找随机文件中的信息 例:把若干个32位的整数写到一个名为 “temp.dat”的文件中,然后利用seek方法,以相反的顺序再读取这些数据 pos
3.6 文件的其它操作 使用文件类获取文件的路径信息 设f是一个文件对象 3.6 文件的其它操作 使用文件类获取文件的路径信息 设f是一个文件对象 File f=new File(“data”,temp.dat”); f.getName():返回文件名 temp.dat f.getParent():返回文件所在目录名 data f.getPath():返回文件路径 data\temp.dat f.getAbsolutePath():返回绝对路 c:\myprog\data\temp.dat
3.6 文件的其它操作 例: 获取当前目录下所有文件名和文件的尺寸: import java.io.*; public class file_size { public static void main(String args[]) { File files=new File(“.”); 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()); }
3.7 java 中的unicode 在java中用unicode 表示字符和字符串 DatainputStream的readLine方法, 以字节形式读入, 以unicode形式输出 DataInputStream不适合输入是unicode的形式 处理字符用InputStreamReader 类和BufferedReader 类(jdk1.1) byte Unicode 16bit 8 bit + 00000000
3.7 java 中的unicode import java.io;(从键盘上读一个字符串) public class CharInput { public static void main(String args[]) {String s; throws IOException InputStreamReader ir; BufferedReader in; ir=new InputStreamReader(System.in); in=new BufferedReader(ir); String s=in.readLine(); int i=Integer.parseInt(s); i=i*2; System.out.println(“the result is” +i); } 可以将字符串转换成整数加以运算 123
3.7 java 中的unicode 问题: 如果字符流不是来自本地,有可能编码不一样,直接读取会读出不正确字符 处理方法: ir=new InputStreamReader(is,”8859_1”); 采用的是iso8859_1编码方式,在不同平台之间正确转换字符.
3.7 java 中的unicode import java.io.*; class filetounicode { public static void main(String args[]) { try{ FileInputStream fis=new FileInputStream("toyamei.txt"); InputStreamReader dis=new InputStreamReader(fis); BufferedReader reader=new String s; BufferedReader(dis); while((s=reader.readLine())!=null) { System.out.println("read: "+s);} dis.close(); }catch(IOException e) { } }
3.8 使用管道流 输出流 输入流 PipedInputStream和PipedOutputStream 创建管道流: PipedInputStream pis=new PipedInputStream(); PipedOutputStream pos=new PipedOutputStream(pis); 或: PipedOutputStream pos=new PipedOutputStream(); PipedInputStream pis=new PipedInputStream(pos);
3.8 使用管道流 管道流一定是输入输出并用 例:将数据从输出管道进,从输入管道出 import java.io.*; class pipedstream { public static void main(String args[]) throws IOException { byte aByteData1=123, aByteData2=111; PipedInputStream pis= new PipedInputStream(); PipedOutputStream pos= new PipedOutputStream(pis); System.out.println("PipedInputStream");
3.8 使用管道流 try{ pos.write(aByteData); pos.write(aByteData2); 3.8 使用管道流 try{ pos.write(aByteData); pos.write(aByteData2); System.out.println((byte)pis.read()); } finally { pis.close(); pos.close(); }
3.9 对象流 在java.io包中什么是对象的持续性? 能够纪录自己的状态一边将来再生的能力,叫对象的持续性 什么是串行化? 对象通过写出描述自己状态的的数值来记录自己的过程叫串行化. 什么是对象流? 能够输入输出对象的流. 两者什么关系? 将串行化的对象通过对象输入输出流写入文件或传送到其它地方.
3.9 对象流 一个相关的例子:从一个源读入一个简单的对象 import java.net;import java.io public class GetString { public String getStringFromUrl(URL inURL) { InputStream in; try { in =inURL.openStream(); }catch(IOException ioe) {System.out.printlin(“URL error;”+ioe); return null; } return getString(in); }通过url得到一个字符串
3.9 对象流 public String getStringFromSocket(Socket inSocket) { inputStream in; try{ in=inSocket.getInputStreamSream(); }catch(IOEception ioe) { System.out.println(“Socket error:”+ioe); return null; } return getString(in); } 通过socket得到一个字符串
3.9 对象流 public String getString(inputStream inStream) { String readString = new String(); DataInputStream in =new DataInputSream(inStream); char inChar; try{ while(true) { inChar=in.readByte(); readString=readString+inChar; } }catch(EOFException eof) { System.out.println(readString);} }catch(IOException ioe) { { System.out.println(“error:”+ieo);} return readString; }
3.9 对象流 下面的对象能读吗? Class testObject { int x; int y; float angle; String name; public testObject(int x,int y,float angle, String name); { this.x=x;this.y;this.angle;this.name=name;} } 这仍然是一个简单的对象
3.9 对象流 对象流是怎样工作的? 允许可串行化的对象在流中传输 1.只有实现serializable接口的类才能被串行化 public class Student implements Serializable { int id;String name; int age; String department; public Student(int id, String name,int age, String department) { this.id=id; this.name=name; this.age=age; this.department =departmernt; }
3.9 对象流 2. 构造对象的输入输出流(将对象保存到文件中,或者通过网络传送到其他地方) 相应的类:ObjectInput 对象的输出: ObjectOutputStream 相应的方法:writeObject() 对象的输入:ObjectInputStream 相应的方法:readObject() 注:jdk1.1以上版本支持对象流操作
3.9 对象流 对象流举例:将Student类的一个实例写到文件中 import java.io.FileOutputStream; import java.io.ObjectOutputStream; public class Objectser {public static void main(String args[]) Student stu=new Student(981036,“Li Ming”,16,“CSD”); {try {FileOutputStream fo=new FileOutputStream(“date.ser”); ObjectOutputStream so=new ObjectOutputStream(fo); os.writeObject(stu);so.close(); }catch(Exception e) {;} }
3.9 对象流 import java.io.FileInputStream; import java.io.ObjectInputStream; public class ObjectRecov { public static void main(String args[]) { Student stu; try {FileInputStream fi=new FileInputStream(“date.ser”); ObjectInputStream si=new ObjectInputStream(fi); stu=(Student)si.readObject();si.close(); }catch(Exception e) {System.out.println(e);} System.out.println(“ID: ”+stu.id+“name:”+ stu.name+“age:”+age+“dept.:”+stu.department); }
3.10 流的分类 InputStream和OutputStream是所有输入输出流的祖先,它们是一个抽象类.System.in和System.out是它们的子类 InputStream FileInputStream PipedIntputStream FilterInputStream ByteArrayInputStream DataInputStream BufferedInputStream LineNumberInputStream SequencedInputStream StringBufferInputStream PushbackInputStream
3.10 流的分类 InputStream和OutputStream是所有输入输出流的祖先,它们是一个抽象类.System.in和System.out是它们的子类 InputStream FileInputStream PipedIntputStream FilterInputStream ByteArrayInputStream DataInputStream BufferedInputStream LineNumberInputStream SequencedInputStream StringBufferInputStream PushbackInputStream
3.10 流的分类 FileOutputStream DataOutputStream PipeOutputStream FilterOutputStream ByteArrayOutputStream DataOutputStream BufferedOutputStream PrintStream InputStream中的基本方法包括: read, available, mark, skip, reset, markSuppposed, close OutputStream中的基本方法包括: write, flush, close
3.11 小结 在Java中有数据传输的地方都用到I/O流 (通常是文件,网络,内存和标准输入输出等) 3.11 小结 在Java中有数据传输的地方都用到I/O流 (通常是文件,网络,内存和标准输入输出等) InputStream 和OutputStream是所有I/O流的祖先(只有RandomAccessFile类是一个例外),read和write是它们最基本的方法,读写单位是字节. 在众多的流对象中,并不是每一种都单独使用,其中过滤流的子类在数据送出去之前做必要的处理. 文件 文件输入流 缓冲输入流 行号输入流 数据输入流 目的
3.11 小结 File, File(Input/Output)Stream, RandomAccessFile是处理本地文件的类 Data(Input/Output)Stream是一个过滤流的子类,借此可以读写各种基本数据, 在文件和网络中经常使用.如: readByte, writeBoolean等. Buffered(Input/Output)Stream的作用是在数据送到目的之前先缓存,达到一定数量时再送到目的,已减少阻塞次数. Piped(Input/Output)Stream适合与一个处理的输出作为另一个处理的输入的情况
结束