字节流
InputStream输入字节流
InputStream的作用是从不同数据源产生输入的类。数据源包括:
- 字节数组
- String对象
- 文件
- 管道
- 其他,如Internet
每一个数据源都有相应的InputStream子类。另外FilterInputStream也属于一种InputStream,为装饰器类提供基类。装饰器类可以把属性或有用的接口与输入流连接在一起。
InputStream类型有:
ByteArrayInputSream
StringBufferInputStream
FileInputStream
PipedInputStream
SequenceInputStream
FilterInputStream
OutputStream字节输出流
OutputStream决定了输出所要去的目标:字节数组、文件或管道。
FilterOutputStream为装饰器类提供了一个基类。
OutputStream主要类型有:
ByteArrayOutputStream
FileOutputStream
PipedOutputStream
FilterOutputStream
装饰器必须具有和它所装饰的对象相同的接口,但可以扩展接口。装饰器模式也有缺点:虽然在写程序时,给我们提供了相当多的灵活性但也增加了代码复杂性,我们必须创建许多类—核心IO类型加上所有的装饰器,才能得到我们所希望的单个IO对象。
FilterInputStream和FilterOutputStream分别来自基类,它们是装饰器的必要条件。
FilterInputStream
通过FilterInputStream从InputStream读取数据。
FilterInputStream的子类有:
DataInputStream
BufferedInputStream
LineNumberInputStream
PushBackInputStream
DataInputStream允许我们读取不同的基本数据类型以及String对象。搭配相应的DataOutputStream我们就可以通过数据流将基本数据类型的数据从一个地方迁移到另一个地方。
其他FilterInputStream类在内部修改InputStream的行为方式:是否缓冲,是否保留它所读过的行等。
FilterOutputStream
通过FilterInputStream向InputStream写入数据。
FilterOutputStream的子类有:
DataOutputStream
PrintStream
BufferedOutputStream
其中PrintStream最初目的是为了可视化格式打印所有的基本数据类型以及String对象。这个DataOutputStream不同,后者目的是将数据元素置入流中,使DataInputStream能可移植的重构他们。BufferedOutputStream是一个修改过的OutputStream,他对数据流使用缓冲技术,所以每次向流写入时不必每次都进行实际的物理写作。
字符流
Reader和Writer
为了把字节层次和字符层次结合起来,产生了一个适配器类:InputStreamReader可以把InputStream转换成Reader,OutputStreamWriter可以把OutputStream转换成Writer
public class FileTest {
public static String read(String filename) throws IOException{
BufferedReader in = new BufferedReader(new FileReader(filename));
String string ;
StringBuilder sb = new StringBuilder();//StringBuilder是线程不安全的,但可用在单线程中。StringBuffer是线程安全的,但消耗会很大
while ((string=in.readLine())!=null) //字符形式
sb.append(string+"\n");
in.close();
return sb.toString();
}
public static void main(String[] args) throws IOException {
System.out.println(read("b.txt"));
//从内存输入
StringReader sr = new StringReader(FileTest.read("b.txt"));
int c;
while((c= sr.read())!=-1)
System.out.println((char)c);
//以字节形式
DataInputStream ds = new DataInputStream(
new ByteArrayInputStream(FileTest.read("b.txt").getBytes()));
while(true)
System.out.print((char)ds.readByte());
//以字节的形式
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("b.txt")));
while(dis.available()!=0){
System.out.println((char)dis.readByte());
}
}
}
以下是基本的文件输出
public class StreamTest {
static String file ="b.txt";
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new StringReader(FileTest.read("a.txt")));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));//new BufferedWriter(new FileWriter(file))也可以直接换成file,这是快捷方式
int linecount = 1;
String string;
while((string=br.readLine())!=null){
pw.println(linecount+++":"+string);
}
pw.close();
System.out.println(FileTest.read(file));
}
}
注意一旦读完数据流一定要显式的调用close()。如果部位输出文件调用close()就会发现缓冲区内容不会被刷新清空,那么他们也就不会完整。
public class StoreAndRecover {
public static void main(String[] args) throws IOException {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("a.txt")));
dos.writeDouble(3.134);
dos.writeUTF("that is pi");
dos.close();
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("a.txt")));
System.out.println(dis.readDouble());
System.out.println(dis.readUTF());
}
}
存储和恢复数据,如果我们使用DataOutputStream写入数据,java保证我们可以使用DataInputStream准确的读取数据。