-- 作者:admin
-- 发布时间:2006/2/26 22:11:06
-- 课件20下载——输入输出流
1 简介 Java的输入输出流使用统一的类库访问方法,解决了程序和外设(如文件、网络、屏幕、键盘等)间的数据交换问题。
这些流类可以按照不同的标准分为不同的类集: 如果按照处理数据信息的方向,可以分为输入流和输出流。所谓的输入和输出是相对于程序而言的,也就是说,输入流是指从外部向程序输入数据信息,输入流是指从程序向外部输出数据信息。
如果按照处理的数据信息类型,主要分为两部分,一为字节流类,二为字符流类。其中字节流类的基类是InputStream与OutputStream,它们都是抽象类,用于二进制信息的处理;字符流类的基类是Reader与Writer,也都是抽象类,用于对16位字符的处理提供简单的做法。
如果按照类本身的功能是否独立可以分为数据流类和处理流类,前者处理真实的数据信息(如字符串、文件、管道等),而后者处理诸如缓冲或者字符编码等,只能通过操纵数据流类来处理数据。
2、文件输入和输出 文件输入和输出仅仅是众多流处理功能的一个,当然也是比较重要的一个
2、1 基于字节流的文件处理 2、1、1 文件字节输入流 基类为InputStream,在创建时自动打开数据流,利用close()显式关闭。如果没有正常关闭或者flush,文件信息将会丢失。
常用的方法有: int read():从输入流中读入一个字节,并且返回0到255之间的整数。如果到达流尾,则返回为-1。 long skip(long):指定跳过多少字节,返回实际跳过的字节数量(有时因为提前到达文件尾从而实际跳过的字节数小于指定的数值)。如果为负,则没有跳过任何字节。
下面的程序演示了文件长度的输出: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileInputStream fis=new FileInputStream("Hello.txt"); System.out.println(fis.available()); } }
也可以使用File类对象获取文件长度,如: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { File f=new File("Hello.txt"); System.out.println(f.length()); } }
当然,这两种方式并不一样,如下面的例子显示了available和length()的区别: import java.io.*; import java.util.*;
public class exec { public static void main(String[] args)throws IOException { byte[] bt=new byte[4]; File f=new File("Hello.txt"); System.out.println(f.length()); FileInputStream fio = new FileInputStream(f); int i=fio.read(bt); String temp=new String(bt); System.out.println(fio.available()); System.out.println(temp); fio.close(); } } 说明:available实际含义为文件可以访问但还尚未访问的字节数,由于刚打开文件,所以和文件长度相等,而如果进行了一些文件访问,这个值就会变化,所以真正求文件长度的方法是应该使用File类
下例是显示文件全部内容: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileInputStream fis=new FileInputStream("Hello.txt"); byte[] barray=new byte[fis.available()]; fis.read(barray); String str=new String(barray); System.out.println(str); } } 注意:read方法只能一次一个字节的读取,所以必须通过字节数组来接受文件信息,并且这个数组应该和文件一样长
2、1、2 文件字节输出流 基类为OutputStream,在创建时自动打开数据流,利用close()显式关闭。常用的方法有: void write(int):将指定字节写入输出流,高于八比特的位将会被忽略 void flush():强制写出任何缓冲中的输出字节
如下面的程序将字符‘0’写入文件: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileOutputStream fos=new FileOutputStream("hello.txt",true); fos.write(0x30); fos.close(); } } 注意: 1)如果文件不存在,FileOutputStream会创建文件,并将数据写入文件 2)FileOutputStream构造函数中的true表示追加方式,否则为替换方式
由于此类只支持字节的输出,所以对于其他类型的数据只有在转换为字节后才能向文件输出,如下例将一个字符串写入文件 import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileOutputStream fos=new FileOutputStream("hello.txt",true); fos.write("Hello".getBytes()); fos.close(); } }
2、2 基于字符流的文件处理 2、2、1 文件字符输入流 基类为Reader,面向Unicode字符,能够读取任何字符从而实现了国际化。和InputStream和OutputStream一样,在创建时自动打开数据流,利用close()显式关闭
如使用字符方式读取文件的一个字符: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileReader fr=new FileReader("Hello.txt"); System.out.println((char)fr.read()); } }
使用字符方式读取文件全部信息的例子: import java.io.*; import java.util.*;
public class exec { public static void main(String[] args)throws IOException { File file = new File("Hello.txt"); int size = (int)file.length(); FileReader in = new FileReader(file); char[] data = new char[size]; in.read(data, 0, size); System.out.println(new String(data)); in.close(); } }
2、2、2 文件字符输入流 基类为Writer,面向Unicode字符,能够写入任何字符从而实现了国际化。和Read、InputStream和OutputStream一样,在创建时自动打开数据流,利用close()显式关闭
如下面的程序向文件输出字符串: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileWriter fw=new FileWriter("Hello.txt"); fw.write("hello!"); fw.close(); } }
2、3 在基于字节的流类和基于字符的流类进行转换 下面考虑一个程序,可以从键盘输入信息,以回车结束,保存到文件,再读取显示在屏幕上: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { byte[] inarray=new byte[10]; int index=0; while(true) { int ch=System.in.read(); if(ch==13) break; else { inarray[index]=(byte)ch; index++; } } FileOutputStream fos=new FileOutputStream("hello.txt"); for(int i=0;i<index;i++) fos.write(inarray); fos.close(); File f=new File("Hello.txt"); FileInputStream fis=new FileInputStream("Hello.txt"); for(index=0;index<f.length();index++) System.out.print((char)fis.read()); } } 注意:这个程序存在两个问题,一是代码相当繁琐,二是对于输入的中文信息无法正确显示在屏幕上。此时可以考虑使用使用基于字符的处理方式,但是很多情况下,我们只能获得基于字节的流对象,这时就可以使用InputStreamReader将基于字节的输入流转换为基于字符的输入流,使用OutputStreamWriter将基于字节的输出流转换为基于字符的输出流,同时这些类还支持字符集的转换
上述代码修改为: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { InputStreamReader isr=new InputStreamReader(System.in,"GBK"); char[] inarray=new char[1000]; isr.read(inarray);
FileOutputStream fos=new FileOutputStream("hello.txt"); OutputStreamWriter osw=new OutputStreamWriter(fos,"GBK");
for(int i=0;i<inarray.length;i++) osw.write(inarray); osw.close(); osw=new OutputStreamWriter(System.out,"GBK"); for(int i=0;i<inarray.length;i++) osw.write(inarray); osw.close(); } }
2、4 功能流类的使用 单纯使用上述流类并不有时十分方便,如上述的流类,只能按照逐字节或者整个字节数组进行输入,有时需要按照按行输入(以回车键为结束标记)就不是非常方便了。一些常用的功能流类可以解决这些问题
2、4、1 缓冲流类 包含BufferedReader和BufferedWriter,提供了很多很好用的方法,如newLine()和readLine()方法等 import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileOutputStream fos=new FileOutputStream("Hello.txt"); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos)); bw.write("Hello!"); bw.newLine(); bw.write("Bye!"); bw.close(); FileInputStream fis=new FileInputStream("Hello.txt"); BufferedReader br=new BufferedReader(new InputStreamReader(fis)); System.out.println(br.readLine()); } }
利用这些方法可以方便的实现文本文件的拷贝,如: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileInputStream fis=new FileInputStream("Hello.txt"); BufferedReader br=new BufferedReader(new InputStreamReader(fis)); FileOutputStream fos=new FileOutputStream("Hello.bak"); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos)); while(true) { String line=br.readLine(); if(line==null) break; else { bw.write(line+"\\n"); } } br.close(); bw.close(); } }
2、4、2 PrintWriter 包含一些使生成格式化输出变得更简单的方法,如println()方法等 import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileOutputStream fos=new FileOutputStream("Hello.txt"); PrintWriter pw=new PrintWriter(fos); pw.println("Hello!"+1); pw.println(true); pw.close(); } }
3、流类在异种设备上的使用 不同的硬件设备具有不同的输入和输出方式,然而使用流类可以将具体的操作细节屏蔽掉,通过流类对象可以使用一种统一的方式来对这些设备进行访问
如下面的程序能够读入一个文件中的一行,存放在另一个文件中: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { FileInputStream fis=new FileInputStream("Hello.txt"); BufferedReader br=new BufferedReader(new InputStreamReader(fis)); FileOutputStream fos=new FileOutputStream("Hello.bak"); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos));
String line=br.readLine(); bw.write(line+"\\n"); br.close(); bw.close(); } }
再如下面这个相似的程序能够从键盘读入一行,存放在另一个文件中: import java.io.*;
public class exec { public static void main(String[] args)throws IOException { BufferedReader br=new BufferedReader(new InputStreamReader(System.in,"GBK")); FileOutputStream fos=new FileOutputStream("Hello.bak"); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos));
String line=br.readLine(); bw.write(line+"\\n"); br.close(); bw.close(); } }
甚至在网络上的通信中,也有相似的代码,如下面的程序片段能够获取网络服务器传来的一行文本信息: BufferedReader is=new BufferedReader( new InputStreamReader(socket.getInputStream())); String readline; readline=sin.readLine();
4 File类 提供定位本地文件系统、描述文件和目录的功能,其中的诸多方法相当有用。 import java.io.*; import java.util.*;
public class exec { public static void main(String[] args)throws IOException { File fl=new File("files","Hello.txt"); System.out.println(fl.getName()); System.out.println(fl.getPath()); System.out.println(fl.getAbsolutePath()); System.out.println(new Date(fl.lastModified())); System.out.println(fl.exists()); System.out.println(fl.isDirectory()); System.out.println(fl.isFile()); if(fl.canRead()) System.out.println("Can Read!"); else System.out.println("Can not Read!"); if(fl.canWrite()) System.out.println("Can Write!"); else System.out.println("Can not Write!"); } } 上述程序在没有Hello.txt文件的时候,输出为 Hello.txt files\\Hello.txt C:\\Documents and Settings\\Administrator\\桌面\\共享资源\\files\\Hello.txt Thu Jan 01 08:00:00 CST 1970 false false false Can not Read! Can not Write!
上述程序在有Hello.txt文件的时候,输出为 Hello.txt files\\Hello.txt C:\\Documents and Settings\\Administrator\\桌面\\共享资源\\files\\Hello.txt Sat Sep 17 07:59:22 CST 2005 true false true Can Read! Can Write!
上述程序在有Hello.txt文件并且为只读属性的时候,输出为 Hello.txt files\\Hello.txt C:\\Documents and Settings\\Administrator\\桌面\\共享资源\\files\\Hello.txt Sat Sep 17 07:59:22 CST 2005 true false true Can Read! Can not Write!
通过File类可以遍历目录文件 import java.io.*;
public class exec { public static void main(String[] args)throws IOException { File f=new File(System.getProperty("user.dir")); File files[]=f.listFiles(); for(int i=0;i<files.length;i++) { System.out.print(files.getName()); if(files.isDirectory()) System.out.println("\\t<dir>"); else System.out.println("\\t"+files.length()); } } }
进一步遍历下级子目录中的文件 import java.io.*;
public class exec { public static void main(String[] args)throws IOException { seeIt(System.getProperty("user.dir")); } public static void seeIt(String str) { File f=new File(str); File files[]=f.listFiles(); for(int i=0;i<files.length;i++) { System.out.print(files.getName()); if(files.isDirectory()) { System.out.println("\\t<dir>"); seeIt(files.getPath()); } else System.out.println("\\t"+files.length()); } } }
[此贴子已经被作者于2010-12-12 08:04:00编辑过]
|