2.输入和输出
public abstract class InputStream extends Object implements Closeable此抽象类是表示字节输入流的所有类的超类。
直接已知子类:AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
public abstract class OutputStream extends Object implements Closeable, Flushable
此抽象类是表示输出字节流的所有类的超类。
直接已知子类:ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream
3.添加属性和有用的借口
Java I/O类库需要多种不同功能的组合,这正是装饰器模式的理由所在。这也是Java I/O类库里存在filter类的原因所在原因抽象类filter是所有装饰器类的基类。装饰器必须具有和它所装饰的对象相同的接口,但它也可以扩展接口。
Java I/O类库操作不便的原因在于:我们必须创建许多类----“核心”I/O类型加上所有的装饰器,才能得到我们所希望的单个I/O对象。
public class FilterInputStream extends InputStream直接已知子类:BufferedInputStream, CheckedInputStream, CipherInputStream, DataInputStream, DeflaterInputStream, DigestInputStream, InflaterInputStream, LineNumberInputStream, ProgressMonitorInputStream, PushbackInputStream
public class DataInputStream extends FilterInputStream implements DataInput
DataInputStream允许我们读取不同的基本类型数据以及String对象(所有方法都以“read”开头,readInt()等)。搭配相应的DataOutputStream,就可以通过数据“流”将基本类型的数据从一个地方迁移到另一个地方。
public interface DataInput
DataInput接口用于从二进制流中读取字节,并根据所有Java 基本类型数据进行重构。
public interface DataOutput
DataOutput接口用于将数据从任意Java基本类型转换为一系列字节,并将这些字节写入二进制流。
public class FilterOutputStream extends OutputStream
直接已知子类:BufferedOutputStream, CheckedOutputStream, CipherOutputStream, DataOutputStream, DeflaterOutputStream, DigestOutputStream, InflaterOutputStream, PrintStream
4.Reader和Writer
InputStream和OutputStream在以面向字节形式的I/O提供极有价值的功能,Reader和Writer则提供兼容Unicode与面向字符的I/O功能。
public abstract class Reader extends Object implements Readable, Closeable用于读取字符流的抽象类。
直接已知子类:BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
写入字符流的抽象类。
直接已知子类:BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter
public class FileReader extends InputStreamReader
有时我们必须把来自于“字节”层次结构中的类和“字符”层次结构中的类结合起来使用。为了实现这个目的,要用到“适配器”类:InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer。
设计Reader和Writer继承层次结构主要是为了国际化。老的I/O流继承层次结构仅支持8位字节流,并且不能很好地处理16位的Unicode字符。由于Unicode用于字符国际化(Java本身的char也是16位的Unicode),所以添加Reader和Writer继承层次结构就是为了在所有的I/O操作中都支持Unicode。
对于InputStream和OutputStream来说,我们会使用FilterInputStream和FilterOutputStream的装饰器子类来修改“流”以满足特殊需要。Reader和Writer的类继承层次结构继续沿用相同的思想---但是并不完全相同。尽管BufferedInputStream是FilterInputStream的子类,但是BufferedReader并不是FilterWriter的子类。
public class BufferedReader extends Reader
public class BufferedWriter extends Writer
5.自我独立的类:RandomAccessFile
RandomAccessFile适用于由大小已知的记录组成的文件,所以可以使用seek()将记录从一处转移到另一处。
public class RandomAccessFile extends Object implements DataOutput, DataInput, Closeable
RansomAccessFile不是InputStream或者OutputStream继承层次结构中的一部分。getFilePointer(),seek(),length()。
另外,其构造器还需要第二个参数,用来指示是“随机读”(r)还是“既读又写”(rw)。它并不支持只写文件。
6.I/O流的典型使用方式
//缓冲输入文件
public class BufferedInputFile {
public static String read(String filename) throws IOException{
BufferedReader in = new BufferedReader(new FileReader(filename));
String s;
StringBuilder sb = new StringBuilder();
while((s=in.readLine()) != null){
sb.append(s+"\n");
}
in.close();
return sb.toString();
}
public static void main(String[] args) throws IOException{
System.out.println(read(System.getProperty("user.dir") + "\\src\\BufferedInputFile.java"));
}
}
//从内存输入
public class MemoryInput {
public static void main(String[] args) throws IOException {
StringReader sr = new StringReader(BufferedInputFile.read("src\\BufferedInputFile.java"));
int c;
while((c=sr.read()) != -1){
System.out.println((char)c);
}
}
}
//格式化的内存输入
public class FormattedMemoryInput {
public static void main(String[] args) {
try {
//DataInputStream数据输入流允许应用程序以与机器无关方式从基础输入流中读取基本 Java 数据类型。
//ByteArrayInputStream 包含一个内部缓冲区,该缓冲区存储从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
DataInputStream in = new DataInputStream(new ByteArrayInputStream(BufferedInputFile.read("src/FormattedMemoryInput.java").getBytes()));
while(true){
System.out.print((char)in.readByte());
}
} catch (IOException e) {
}
}
}
//基本的文件输出
public class BasicFileOutput {
static String filename = "BasicFileOutput.out";
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new StringReader(BufferedInputFile.read("src/FormattedMemoryInput.java")));
//BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
//PrintWriter向文本输出流打印对象的格式化表示形式
BufferedWriter pw = new BufferedWriter(new FileWriter(filename));
int lineCount=1;
String s;
while((s=in.readLine())!=null){
pw.write(lineCount++ + ": " + s + "\n");
}
pw.close();
System.out.println(BufferedInputFile.read(filename));
}
}
如果不为所有的输出文件调用close(),就会发现缓冲区内容不会被刷新清空,那么它们就不完整。
//存储和恢复数据
public class StoringAndRecoveringData {
public static void main(String[] args) throws IOException {
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("Data.txt")));
out.writeDouble(3.14159);
out.writeUTF("That was pi");
out.writeDouble(1.41413);
out.writeUTF("Square root of 2");
out.close();
DataInputStream in = new DataInputStream(
new BufferedInputStream(
new FileInputStream("Data.txt")));
System.out.println(in.readDouble());
// Only readUTF() will recover the
// Java-UTF String properly:
System.out.println(in.readUTF());
System.out.println(in.readDouble());
System.out.println(in.readUTF());
}
}
8.标准I/O
按照标准I/O模型,Java提供了System.in、System.out和System.err。
System.out和System.err已经实现被包装成了PrintStream(FilterOutputStream子类),但System.in却是一个没有被包装过的未经加工的InputStream。这意味着可以立即使用System.out和System.err,但是在读取System.in之前必须对其进行包装。
//从标准输入中读取
public class Echo {
static void main(String[] args) throws IOException {
System.out.println(123);
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String s;
while((s=stdin.readLine()) != null && s.length() != 0){
System.out.println(s);
}
}
}
//标准I/O重定向
//I/O重定向操纵的是字节流,而不是字符流;因此我们使用的是InputStream和OutputStream,而不是Reader和Writer
public class Redirecting {
public static void main(String[] args)
throws IOException {
PrintStream console = System.out;
BufferedInputStream in = new BufferedInputStream(
new FileInputStream("src/Redirecting.java"));
PrintStream out = new PrintStream(
new BufferedOutputStream(
new FileOutputStream("test.out")));
System.setIn(in);
System.setOut(out);
System.setErr(out);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String s;
while((s = br.readLine()) != null)
System.out.println(s);
out.close(); // Remember this!
System.setOut(console);
}
}