java基础——输入输出流
包java.io定义了很多用来读和写流数据或连续数据的类,其中类InputStream和OutputStream是用来读和写字节流的,而类Reader和Writer是用来读和写字符流的。流是可以嵌套的,也就是说我们可以从FileterReader对象中读取字符,FileterReader对象是用来从潜在的Reader流中读取并处理字符的。这种潜在的Reader流可以从InputSteam中读取字节,在把这些字节转换成字符。
其实我们可以用流来执行很多共同的操作,下面的这个例子就是在操作平台上读取输入的用户信息:
BufferedReader console= new BufferedReader(new InputSteamReader(System.in));
System.out.print("what is your name");
String name=null;
Try{
Name=console.readLine();
}catch(IOException e){
Name="<"+e+">";
}
System.out.print("Hello "+name);
从文件中读取文本行的操作是类似的。下面这段程序执行的就是读取整个文本文件,并且当读到文件尾时终止程序的执行。
Try{
BufferedReader in= new BufferedReader(new FileReader(filename));
String line;
While((line=in.readLine())!=null){
System.out.println(line);
}
In.close();
}catch(IOException e){...}
System.out只是简单地引用了一个输出流。我们可以采用相似的技术在任何输出流中打印文本。下面这段代码告诉我们如何在文件中输入文本:
Try{
File f= new File(homedir,".config");
PrintWriter out = new PrintWriter(new FileWriter(f));
Out.println("## Automatically generated config file. DO NOT EDIT!");
Out.close();
}catch(IOException){...}
但是并不是所有的文件都包含文本。下面这段代码处理文件时,把文件作为一个字节流,并且把这些字节读入到一个大数组中:
Try{
File f;
Int filesize=(int)f.length();
Byte[] data=new byte[filesize];
DateInputSteam in=new DataInputStream(new FileInputStream(f));
in.readFully(data);
In.close();
}catch(IOException e){..}
到目前为止,我们已经用到了很多流类操作流数据,但是最终数据本身都是来自于文件,或是被写入控制台。所以在java.io包中还定义了其他一些流类,这些类不仅允许我们从字节数组或文本字符串中读取数据,而且还允许我们向其中写入数据:
//创建的流把字节数组作为它的读写缓冲区
ByteArrayOutputStream baos= new ByteArrayOutputStream();
DataOutputStream out= new DataOutputStream(baos);
out.writeUTF("hello");
out.writeDouble(Math.PI);
Byte[] data = baos.toByteArray();//得到我们已经输入的字节数组
Out.close();
//创建的流用来从字符串中读取字符
Reader in = new StringReader("Now is the time!") ;
Int c;
While((c=in.read())!=-1) System.out.print((char)c);
其它以这种方式执行的类还包括ByteArrayInputStream,StringWriter,CharArrayReader和CharArrayWriter。
类PipedInputStream和PipedOutputStream以及他们基于字符的另外两个类PipedReader和PipedWriter是java.io定义的其它一些非常有趣的流集合。我们在使用这些流类时一般都是通过两个希望通信的线程成对使用它们,其中一个线程向PipedOutputStream写入字节或向PipedWriter写入字符,而另一个线程用来从相应的PipedInputStream或PipedReader中分别读取字节或字符:
Final PipedOutputStream writeEndOfPipe=new PipedOutputStream();
Final PipedInputStream readEndOfPipe= new PipedInputStream(writeEndOfPipe);
Thread devnull=new Thread(new Runnable(){
Public void run(){
Try {
While(readEndOfPipe.read()!=-1);
}catch(IOException e){...}
}
});
Devnull.start();
Java.io包的一个最重要的特征就是它能够串行化(serialize)对象:也就是说它可以把一个对象转换成字节流,然后再把这个字节流反串行化(deserialize)成原始对象的一个拷贝,下面这段程序告诉我们如何用串行化把对象保存到文件中,并在以后重新从文件中读出该对象:
Object o;
File f;
Try{
ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream(f));
oos.writerObject(o);
Oos.close();
//从文件中重新读出对象
ObjectInputStream ois= new ObjectInputStream(new FileInputStream(f));
Object copy=ois.readObject();
Ois.close();
}catch(IOException e){...}
Catch(ClassNotFoundException cnfe){...//方法readObject()可能会抛出这个异常}