第十一章 java I/O系统
11.2 输入和输出
1.InputStream(输入流) read()方法读取单个字节或者字节数组。
2.Reader 类 字符。如果是关系到中文(文本)的,适用于字符流。
3.OutputStream(输出流) writer()方法写入单个字节或字节数组。
4.Writer类 字符。
字节流适用于 音频文件、图片、歌曲。
字符流适合纯文本,可以使用缓冲区,速度快。
11.2.1 InputStream的类型
1.StringBufferInputStream 字符串转InputStream。
2.FileInputStream 用于从文件中读取信息。
3.SequenceInputStream 将两个或更多的InputStram转换成单个InputStream使用
11.3.1通过FilterInputStream从InputStream里读入数据
1.字节操作 InputStream OutputStream
2.字符操作 Reader Writer
3.InputStreamReader 可将InputStream 转换成Reader
4.Reader和Writer提供国际化,速度快,支持Unicode.
11.5 RandomAccessFile
1.getFilePointer()方法了解当前位于文件何处。
2.Seek() 移文件至新位置
3.Length()判断文件长度
DataInputStream in = new DataInputStream();
While(in.nvailable!=0){
System.out.print((char)in.ReadByte());
}
4..格式化内存输入
DataInputStream in = new DataInputStream{
New BufferedInputStream {
New FileInpuStream(xx.txt);
}
}
While(in.available)!=0
System.out.print((char)in.readByte());
5.文件输出
首先创建一个FileWriter建立 同文件的连接。对输出进行缓冲,封装到一个BuffereWriter里。(缓冲的目的是大幅度提升I/O操作的性能)
举个简单例子,在A地有10000本书需要搬到B地,如果一次搬1本,需要10000次。如果每次取1000本放到一个货车上,运到B地,需要10次完成。货车相当于是缓存区。同样道理,开设一个数据缓存区每次读取一数据块对于提高读取效率有显著提升。下面用一个具体代码示例来表示二者的性能差别。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TestBuffer {
public static void main(String args[]) throws IOException {
TestBuffer br = new TestBuffer();
String from = "D:\\111\\MYTBS01.DBF";
long startTime = System.currentTimeMillis();
br.readWrite(from,"D:\\b\\11.dbf");
long endTime = System.currentTimeMillis();
System.out.println("直接读取耗时:" + (endTime - startTime) +"ms");
long startTime1 = System.currentTimeMillis();
br.readWriteWithBuffer(from, "D:\\b\\112.dbf");
long endTime1 = System.currentTimeMillis();
System.out.println("使用缓冲区读取耗时:" + (endTime1 - startTime1) +"ms");
}
/***************************************************************************
* 直接读取文件
*/
public static void readWrite(Stringfrom, Stringto) throws IOException {
InputStream in =null;
OutputStream out =null;
try {
in =new FileInputStream(from);
out =new FileOutputStream(to);
while (true) {
int data =in.read();
if (data == -1) {
break;
}
out.write(data);
}
} finally {
if (in !=null) {
in.close();
}
if (out !=null) {
out.close();
}
}
}
/***************************************************************************
* 使用缓存区读写文件
*/
public static void readWriteWithBuffer(Stringfrom, Stringto)
throws IOException {
InputStream inBuffer =null;
OutputStream outBuffer =null;
try {
inBuffer =new BufferedInputStream(new FileInputStream(from));
outBuffer =new BufferedOutputStream(new FileOutputStream(to));
while (true) {
int data =inBuffer.read();
if (data == -1) {
break;
}
outBuffer.write(data);
}
} finally {
if (inBuffer !=null) {
inBuffer.close();
}
if (outBuffer !=null) {
outBuffer.close();
}
}
}
}
直接读取耗时:58786ms
使用缓冲区读取耗时:264ms
1.DataInputStream
与 DataOutputStream联合使用 使自己能从一个流中读取原始数据类型 int char long 等等 而且
做到了与具体的运行平台无关 从而保证了程序的移植能力。
2.BufferedInputStream
避免每次想要更多的数据时都进行实际的物理性读取。这相当于你告诉它“先用着缓冲”。
3.PrintStream
用 于 产 生 格 式 化 输 出 注 意,DataOutputStream控制的是数据的“存储” 而PrintStream 控制的是数据的“显示”
11.7 标准I/O
1.System.in / out / err
2.readLine()每次读取一行输入信息。
将 system.in封装到一个BufferedReader中:
先用InputSteramReader将System.in转化为Reader
代码:
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
String s;
while((s = in.readLine()).length() != 0)
System.out.println(s);
System.in通常也应该进行缓冲处理。
11.7.2将system.out变成PrintWriter
1.System.out是一个PrintWriter
2.PrintWriter是一个OutPutStream
代码:
PrintWriter out =
new PrintWriter(System.out, true);
out.println("Hello, world");
True自动刷新缓冲区,若设置为false,则显示空。
3.Java 的 System 类允许我们重新定向标准输入,输出以及错误消息的,I/O流方法是使
用下述三个静态方法之一
setIn(InputStream)
setOut(PrintStream)改变输出流。
setErr(PrintStream)
11.8 压缩
11.8.1 用GZIP进行简单压缩
BufferedOutputStream out = new BufferedOutputStream(
new GZIPOutputStream(
new FileOutputStream("test.gz")));
System.out.println("Writing file");
int c;
while((c = in.read()) != -1)
out.write(c);
in.close();
out.close();
System.out.println("Reading file");
BufferedReader in2 = new BufferedReader(
new InputStreamReader( //stream转Reader 字节流转字符流
new GZIPInputStream(
new FileInputStream("test.gz"))));
String s;
while((s = in2.readLine()) != null)
System.out.println(s);
}
11.9对象序列化
1.可在windows上创建对象将其序列化发送至一台unix机器。
2.将对象序列化,写入磁盘,在以后程序重新调用时重新恢复那个对象
3.为了序列化一个对象,首先要创建某些 OutputStream 对象,然后将其封装到ObjectOutputStream对象内,此 时,只需调用 writeObject()即可完成对象的序列化,并将其发送给 OutputStream。相反的过程是将一个 InputStream封装到ObjectInputStream内,然后调用 readObject()。
4.对象序列化是面向字节的。
11.9.2序列化的控制
1. 通过实现 Externalizable接口
2. 为防止对象的敏感部分被序列化 一个办法是将自己的类实现为 Externalizable就象前面展示的那样 这样一来 没有任何东西可以自动序列化 只能在 writeExternal()内明确序列化那些需要的部分
3. 然而 若操作的是一个 Serializable对象,则使用关键字transient,例如设置为transient String password
4. 在调用 ObjectOutputStream.writeObject()的时候,似乎会对传递给它的 Serializable对象进行检查,无疑是通过 反射 机制检查的,看它是否实现了自己的 writeObject()若答案是肯定的,便会跳过常规的序列化过程,并调用 writeObject(),readObject()也会遇到同样的情况。
5. 序列化要注意的问题是安全,因为序列化也会将private保存下来,若需要保密则标记为transient。
11.10记号式输入
记号式 Tokenizing是指将一个字符序列分割成一系列记号 Token 这些 记
号 实际是一些文字 中间可用你选择的任何东西加以分隔 例如 你的记号可以是一些句
子 中间用空格和标点符号分隔 在标准 Java库中 有两个类可供我们进行记号式输入
它们分别是 StreamTokenizer和 StringTokenizer。
Worldcount.java 计算单词在文本文件中出现的次数。
StreamTokenizer.ordinaryChar(“.”)表示小数点不会成为解析出来单词的一部分。
StreamTokenizer和StringTokenizer功能相似,进行更复杂的操作,应该使用StreamTokenizer