当前位置:课程学习>>第七章 输入输出流>>文本学习>>知识点二
对于像汉字这样的双字节字符处理,仅有字节流是不方便的,这是因为基本的处理单位不是1字节,而是2字节。由于Java语言中字符是用Unicode双字节表示的,因而在java.io包中提供了专门用于字符流处理的类。以Reader为根类的所有类用于字符的输入,以Writer为根类的所有类用于字符的输出。
一、Reader类和Writer类
Reader和Writer是面向字符输入的,它们以字符(16位)为单位读写,因此效率较InputStream和OutputStream类高。Java建议在可能的情况下,尽量用Reader和Writer。下列表中列出了Reader类和Writer类的常用方法。
表7.5 Reader类的常用方法
方法 |
描述 |
Public int read() throws IOException |
返回字符输入流中读取一个Unicode字符。若读到流结束,则返回-1。若流中暂时无字符可读,则该方法进入阻塞状态 |
Public int read(char cbuf[]) throws IOException |
将cbuf.length字符读入到数组cbuf中,返回实际读入的字符数。若读到流结束,则返回-1。若流中暂时无字符可读,则该方法进入阻塞状态 |
Public abstract int read(char cbuf[],int off,int len) throws IOException |
将len字符读入到数组cbuf[]中,返回实际读入的字符数。若读到流结束,则返回-1。若流中暂时无字符可读,则该方法进入阻塞状态 |
Public Boolean marksupported() |
若流支持mark()操作则返回true,否则返回false |
Public void mark(int readAheadLimit) throws IOException |
给当前流作为标记,最多支持readAheadLimit字符的回溯 |
Public void reset() throws IOException |
将当前流重置到标记处。注:不是所有的字符流都支持mark()和reset() |
Public abstract void close() throws IOException |
关闭流,进一步的读取将会产生IOException异常 |
表7.6 Writer类的常用方法
方法 |
描述 |
Public void write(int c) throws IOException |
将c的低16位写入输出流中,高16位丢弃 |
Public void write(char[] cbuf) throws IOEception |
将字符数组cbuf[]中的所有字符全写到输出流中 |
Public abstract void write(char cbuf[],int off,int len) throws IOException |
将字符数组cbuf[]中从索引off位置处开始的len字符写入到输出流中 |
Public void write(String s) throws IOException |
将字符串s中的所有字符写入到输出流中 |
Public void write(String str,int off,int len) throws IOException |
将字符串str中从索引off开始处的len字符写入到输出流中 |
Public abstract void flush() throws IOException |
刷空输出流,将所有被缓存的字符全写到输出流中 |
Public abstract void close() throws IOException |
先将所有被缓存的字符全写到输出流中,然后关闭流。 |
二、InputStreamReader和OutputStreamWriter
字符流是建立在字节流基础之上的,Java语言内部可将一个字节流按照某种
编码规范转换成字符流,这方面的转换是由字节流与字符流转换的桥类InputStreamReader和OutputStreamWriter来完成的。
(1) InputstreamReader类的构造方法:
Public InputStreamReader(InputStream in)
使用当前平台默认的编码规范,将字节输入流in转换成一个字符输入流。
(2) OutputStreamWriter类的构造方法:
Public OutputStreamWriter(OutputStream out)
使用当前平台默认的编码规范,将字节输出流out转换成一个字符输出流。
以下这两个方法,这两个类都支持。
Public String getEncoding() //返回当前字符流所使用的编码规范
Public void close() throws IOException //关闭流
【例7.12】获取当前平台默认的编码规范
1 //InStreamReaderExample.java
2 import java.io.*;
3 public class InStreamReaderExample {
4 public static void main(String[] args) {
5 InputStreamReader reader = new InputStreamReader(System.in);
6 System.out.println("默认编码规范:" + reader.getEncoding());
7 }
8 }
【例7.13】从键盘上读入汉字,打印出汉字及其Unicode代码。
1 //OutStreamWriterExample.java
2 import java.io.*;
3 public class OutStreamWriterExample {
4 public static void main(String[] args) {
5 Reader rd = new InputStreamReader(System.in);
6 int c;
7 try
8 {
9 while((c=rd.read())!=-1)
10 System.out.println("汉字是:"+(char)c+"Unicode: "+c);
11 }catch(IOException e)
12 {
13 System.out.println(e);
14 }
15
16 }
17 }
该程序的运行结果为:
我们
汉字是:我Unicode: 25105
汉字是:们Unicode: 20204
三、FileReader类和FileWriter类
对字符文件如文本文件的处理是以Unicode字符为基本单位的,尽管在理论上,任何文件都是字节文件,但以字节为单位处理字符文件有时不方便。FileReader类用于字符文件的读,每次读取一个字符或一个字符数组。FileWriter类用于字符文件的写,每次写入一个字符、一个数组或一个字符串。通常将FileReader类的对象视为一个以字符为基本单位的无格式的字符输入流,将FileWriter的对象视为一个以字符为基本单位的无格式的字符输出流。
【例7.14】文本文件的复制:将t1.txt复制到t2.tx中。
1 //FileReaderExample.java
2 import java.io.*;
3 public class FileReaderExample {
4 public static void main(String[] args) throws Exception{
5 try{
6 FileReader fr = new FileReader("E:\\teacher\\course\\java\\javabook\\t1.txt");
7 FileWriter fw = new FileWriter("E:\\teacher\\course\\java\\javabook\\t2.txt");
8 int c;
9 while((c=fr.read())!=-1)
10 fw.write(c);
11 fw.flush();
12 fr.close();
13 fw.close();
14 }catch(FileNotFoundException e)
15 {
16 System.out.println(e);
17 }
18 }
19 }
四、BufferedReader类和BufferedWriter类
文本行是以回车、换行结束的字符序列,以文本行为基本单位进行文本读取与处理有时更方便。BufferedReader类和BufferedWriter类是带缓冲的字符流,可用于以文本行为为基本单位进行处理的场合,比如要求从键盘读入一个整数值123,可将键盘变成一个带缓冲的字符输入流,一下子读入串“123”,然后利用Integer.ParseInt(“123”)转换成整数123。
【例7.15】从键盘上读入一个整数值n,打印出1+2+…+n之和。
1 //BufferedReaderExample.java
2 import java.io.*;
3 public class BufferedReaderExample {
4 public static void main(String[] args) throws Exception{
5 BufferedReader kr = new BufferedReader(new
InputStreamReader(System.in));
6 //键盘转换成一个能读取文本行的字符输入流
7 String s;
8 int n=0;
9 int sum=0,k=0;
10 System.out.println("请输入一个整数值:");
11 s=kr.readLine(); //从键盘读取一行
12 n = Integer.parseInt(s);
13 for(k=1;k<=n;k++)
14 sum=sum+k;
15 System.out.println("1+2+...+n="+sum);
16 }
17 }
五、PrintWriter类
文本文件的输出流有FileWriter类,该类通常是以字符为单位写文本文件。有时需要以Java语言中的基本数据类型为单位进行文本文件的写入,如将实数值12.6以文本方式写入文本文件中。尽管使用FileWriter也能写入,但处理起来不是很方便,Java语言中引入的PrintWriter类可以很方便地进行此类文本文件的输出。PrintWriter流是文本流中使用频率很高的流。
【例7.16】将100以内的所有素数都打印到文本文件中,每行5个数,数之间用逗号分割。
1 //PrintWriterExample.java
2 import java.io.*;
3 public class PrintWriterExample {
4 public static void main(String[] args) throws Exception{
5 PrintWriter pw = new PrintWriter(new FileWriter("tp.txt"),true);
6 int k,j,cc=0;
7 again:for(k=2;k<100;k++)
8 {
9 for(j=2;j<=k/2;j++)
10 if(k%j==0) continue again; //若k不是素数则继续下一个
11 pw.print(k);
12 cc++;
13 if(cc==5) //每5个换1行
14 {
15 cc=0;
16 pw.println();
17 }
18 else
19 pw.print(","); //向文件中输出逗号
20 }
21 pw.close();
22 }
23 }
该程序的输出结果为:
2,3,5,7,11
13,17,19,23,29
31,37,41,43,47
53,59,61,67,71
73,79,83,89,97
六、File类及其应用
前面介绍的类基本上是对文件的内容进行处理,例如在文件中读取或存储数据。当需要读取数据的文件不存在时往往不能直接做出判断,而必须通过异常才能得到这种信息。类java.io.File很好地解决了这个问题。
File类是java.io程序包中的一个类,它是对文件系统中文件和文件夹的抽象,一般不涉及文件内部的具体内容,而是从整体上对文件进行处理,如获取各种各样的文件信息或删除文件。类File不仅可以对文件进行操作,还可以对路径进行操作。下面介绍File类的构造方法及常用方法。
表7.7 File类的构造方法及常用方法
方法 |
描述 |
Public File(String name) |
指定与File对象关联的文件或目录的名称。Name可以包含路径信息及文件或目录名。 |
Pulbic File(String pathToName,String name) |
使用pathToName来定位参数name所指定的文件或目录 |
Public File (File directory, String name) |
使用现有的File对象directory(绝对路径或相对路径)来定位参数name所指定的文件或目录 |
Public File(URI uri) |
使用给定的URI对象来定位文件 |
isFile() |
判断指定的File实例是否是文件 |
isDirectory() |
判断指定的File实例是否是路径 |
canRead() |
判断当前文件是否可读 |
canWrite() |
判断当前文件是否可写 |
compareTo() |
按词典顺序比较两个抽象路径名或者对象 |
delete() |
删除文件或者目录 |
deleteOnExit() |
当虚拟机结束时删除实例所表示的文件或者文件夹 |
exists() |
检测与文件对象实例对应的文件是否存在 |
getAbsoluteFile() |
返回文件的绝对路径 |
length() |
返回文件长度 |
list() |
以数组的形式返回目录中的文件名 |
getName() |
返回文件对象的名称 |
getParent() |
返回字符串类型的文件对象的上级目录,如果没有则为空 |
getParentPath() |
返回文件类型的文件对象的上级目录 |
getPath() |
得到抽象路径名对应的路径字符串 |
hashCode() |
为文件对象计算hash值 |
isAbsolute() |
检测抽象路径名是否是绝对的 |
listFiles() |
以文件数组的形式返回目录中的文件 |
listRoots() |
返回可用的系统根目录 |
mkdir() |
创建目录 |
toString() |
返回文件实例的路径名 |
【例7.18】File类的应用示例。
1 //FileExample.java
2 import java.io.*;
3 public class FileExample {
4 public static void main(String[] args) {
5 for(int i=0;i<args.length;i++)
6 {
7 File f = new File(args[i]);
8 if(f.exists())
9 {
10 System.out.println("getName:" + f.getName());
11 System.out.println("getPath:" + f.getPath());
12 System.out.println("getAbsolutePath:" + f.getAbsolutePath());
13 System.out.println("getParent:" + f.getParent());
14 if(f.canWrite())
15 System.out.println(f.getName() + "is writable.");
16 if(f.canRead())
17 System.out.println(f.getName() + "is readable.");
18 if(f.isFile())
19 System.out.println(f.getName() + "is a file.");
20 else if(f.isDirectory())
21 System.out.println(f.getName() + "is a directory.");
22 else
23 System.out.println("What is this?");
24 if(f.isAbsolute())
25 System.out.println(f.getAbsolutePath() + "is an absolute path.");
26 else
27 System.out.println(f.getName() + "is not an absolute path.");
28 System.out.println("Last Modified:" + f.lastModified());
29 System.out.println(f.getName() + "is" + f.length() + "bytes.");
30 }
31 else
32 System.out.println("Can't find the file" + args[i]);
33 }
34 }
35 }