java流式输入/输出原理
File类
File类的对象主要用来获得文件本身的信息,并不涉及对文件的读写(读写是用流来操作)。
构造方法:
- File(String filename)
- File(String directoryPath,String filename)
- File(File dir,String filename)
流
对于输入和输出的判断,由于参照系文件和程序而言输入输出时相反的,一般是从程序上判断输入输出的概念(向程序输入(In)向程序输出(Out))。
节点流
节点流是数据源和程序直接连接。
- 父 类 :InputStream 、OutputStream、 Reader、 Writer
- 文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
- 数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
- 字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
- 管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流
字节流
InputStream(抽象类):向程序输入数据,单位字节(8bit)
子类FileInputStream
- 基本方法:(均抛出IOException)
– int read() / (byte[] buffer) / (byte[] buffer,int offset,int length)
– void close()
– long skip(long n)
OutputStream(抽象类):向程序输出数据,单位字节(8bit)
子类FIleOutputStream
- 基本方法:(均抛出IOException)
– int write() / (byte[] buffer) / (byte[] buffer,int off,int len)
– void close()//关闭流释放内存
– void flush()…常写在close()前确保缓冲区输出完毕
字符流
Reader(抽象类):向程序输入数据,单位字符(16bit)
子类FileReader
- 基本方法:(均抛出IOException)
– int read() / (char[] buffer) / (char[] buffer,int offset,int length)
– void close()
– long skip(long n)
Writer(抽象类):向程序输出数据,单位字符(16bit)
子类FileWriter
- 基本方法:(均抛出IOException)
– int write() / (char[] buffer) / (char[] buffer,int off,int len) / (String string) / (String string,int off,int len)
– void close()
– void flush()//将流中缓冲数据写到目的地
随机流
随机流既可以用来读取文件也可以用来写入文件(rw读写,r只读)
RandomAccessFile raf = new RandomAccessFile(new File(“1.txt”),“rw”);
数据流与数组流
数据流需要套接到字节流,提供了存取与机器无关的java原始类型构造方法:
DataInputStream(InputSream);
DataOutputStream(OutputStream);
ByteArrayInputStream
ByteArrayOutputStream
貌似可以用来输入输出多类型文件
public class test2 {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try{
dos.writeDouble(Math.random());
dos.writeBoolean(true);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
System.out.println(bais.available());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
}catch (IOException e){
e.printStackTrace();
}
}
}
队列,先写进去先读出来
对象流
ObjectInputStream(InputStream in)
ObjectOutputStream(OutputStream out)
使用对象流写入读取对象需要对象序列化;
序列化与对象克隆
一个类如果实现了Serializable接口,这个类的实例对象就是可序列化的
Serializable接口抽象方法不可见,当把序列化对象写入对象流时在jvm中实现接口方法
我们知道,两个对象具有相同的引用这两个对象相同
A one = new A();
A two = one;
这个时候我们对one和two操作其实都是对一个实例对象进行操作(相当于一个对象两个引用)
并不能达到对象克隆的目的
使用对象流很容易获得序列化对象的克隆
处理流
处理流是“连接”在已存在的流(节点流或处理流)上,通过数据处理为程序提供强大读写功能。(套管道过滤)
处理流:BufferedInputStream/BufferedOutputStream
缓冲流
缓冲流要套接在节点流之上进行处理,提高了读写效率增加了新的方法。(对硬盘友好)
字节缓冲流
public class Test1 {
public static void main(String[] args) throws IOException {
try{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\code cor\\项目\\1.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\code cor\\项目\\2.txt",true));
int b;
while((b=bis.read())!=-1){
bos.write(b);
}
} catch (IOException e){
e.printStackTrace();
} finally{
bis.close();
bos.flush();
bos.close();
}
}
}
字符缓冲流:
public class Test2 {
public static void main(String[] args) throws IOException {
BufferedReader bis = null;
BufferedWriter bos = null;
try{
bis = new BufferedReader(new FileReader("1.txt"));
bos = new BufferedWriter(new FileWriter("2.txt",true));
String str;
while((str=bis.readLine())!=null){
bos.write(str);
}
} catch (IOException e){
e.printStackTrace();
} finally {
bis.close();
bos.flush();
bos.close();
}
}
}
转换流
InputStreamReader和OutputStreamWriter将字节流转换为字符流(写中文不用强转)
Io流的关闭(大问题)
I/O资源使用完后需要关闭(调用流的close()方法),否则可能会遇到一些奇怪的bug
关闭顺序:先打开的后关闭
I/O流使用了装饰模式,关闭处理流时会关闭对应的节点流
更多输入输出流方法查询API文档:API文档(中文)