IO流
Java流式输入输出原理
在Java程序中,对于数据的输入输出操作以流的方式进行,J2SDK提供了各种各样的“流”类,用以获取不同种类的数据,程序中通过标准的方法输入或者输出数据
输入/输出流的分类
Java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能
按照数据流的方向不同可分为输入流和输出流(在程序的角度看)
按照数据处理单位不同可分为字节流和字符流
按照功能不同可以分为节点流和处理流
J2SDK所提供的所有流类型位于包Java.io内都分别继承自一下四中抽象流类型
字节流 | 字符流 | |
---|---|---|
输入流 | Inputstream | Reader |
输出流 | Outoutstream | Writer |
节点流和处理流
节点流为可以从一个特定的数据源(节点)读写数据
处理流是“连接”在医讯在的流(节点流或者处理流)之上,通过对数据的处理为程序提供更为强大的读写功能
InputStream
继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8 bit)
如下图(深色为节点流,浅色为处理流)
InputStream基本方法
读取一个字节并以整数的形式返回(0~255)如果返回-1则已到输入流的末尾 int read() throws IOException读取一系列字节并存储到一个数组buffer,返回实际读取的字节数,如果读取已到输入流的末尾返回-1
Int read(byte[]buffer) throws IOException读取length个字节并存储到一个字节数组buffer,从length位置开始,返回实际读取的字节数,如果读取前已到输入流的末尾返回-1
Int read(byte[] buffer,int offset , int length) throws IOException关闭流释放内存资源 void close() throws IOException
跳过n个字节不读,返回实际跳过的字节数 long skip(long n) throws IOException
OutputStream
继承自OutputStream的流适用于程序中输入数据,且数据的单位为字节(8 bit)
如下图(深色为节点流,浅色为处理流)
OutputStream基本方法
向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException将一个字节类型的数组中的数据写入输入流
void write(byte[] b) throws IOException将一个字节类型的数组中的指定位置(off)开始len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException关闭流释放内存资源
void close() throws IOException将输入流中缓冲的数据全部写出到目的地
void flush() throws IOException
Reader
继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16 bit)
如下图(深色为节点流,浅色为处理流)
Reader的基本方法
读取一个字符并以整数的形式返回(0~255)如果返回-1则已到输入流的末尾
int read() throws IOException读取一系列字节并存储到一个数组buffer,返回实际读取的字节数,如果读取已到输入流的末尾返回-1
Int read(char[] buffer) throws IOException读取length个字符并存储到一个字节数组buffer,从length位置开始,返回实际读取的字符数,如果读取前已到输入流的末尾返回-1
Int read(char[ ] buffer,int offset , int length) throws IOException关闭流释放内存资源 void close() throws IOException
跳过n个字符不读,返回实际跳过的字节数 long skip(long n) throws
Writer
继承自Writer的流都是用于程序中输出数据,且数据的单位为字符(16 bit)
如下图(深色为节点流,浅色为处理流)
Writer的基本方法
向输出流中写入一个字符数据,该字符数据为参数b的低16位
void write(int b) throws IOException将一个字符类型的数组中的数据写入输入流
void write(char[] b) throws IOException将一个字符类型的数组中的指定位置(off)开始len个字节写入到输出流
void write(char[] b,int off,int len) throws IOException将一个字符串中的字符写入到输出流
void write(String string) throws IOException将一个字符串从offset开始的length个字符写入带输出流
void write(String string,int offset,int length) throws IOException关闭流释放内存资源
void close() throws IOException将输入流中缓冲的数据全部写出到目的地
void flush() throws IOException
节点流类型
节点流为可以从一个特定的数据源(节点)读写数据
类型 | 字符流 | 字节流 |
---|---|---|
File(文件) | FileReader、 FileWriter | FileInputStream、 FileOutPutStream |
Memory Array | CharArrayReader CharArrayWriter | ByteArrayInputStream ByteArrayOutputStream |
Memory String | String Reader、String Writer | ————– |
Pipe(管道) | PipedReader、PipedWriter | PipedInputStream、PipedOutputStream |
字节流举例,通过FileInputStream、 FileOutPutStream完成文件复制
public class TestFileStream {
public static void main(String[] args) {
//文件中有文字时将无法识别
FileInputStream in;
FileOutputStream out;
int b = 0;
try {
in = new FileInputStream("d:\\java\\Hello.java");
//当文件中没有Out.java这个文件时,会自动创建
out = new FileOutputStream("d:\\java\\Out.java");
while((b = in.read()) != -1){
out.write(b);
}
in.close();
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print("文件已复制!");
}
}
FileReader、FileWriter类似于FileInputStream、 FileOutPutStream,但利用前者可以完美的打印出中文
处理流类型
前面提到处理流是“连接”在医讯在的流(节点流或者处理流)之上,通过对数据的处理为程序提供更为强大的读写功能
处理类型 | 字符流 | 字节流 |
---|---|---|
Buffering | BufferedReader、BufferedWriter | BufferedInputStream、BufferedOutputStream |
Filtering | FilterReader、FilterWriter | FilterInputStream、FilterOutputStream |
Converting between bytes and character | IntputStreamReader OutputStreamReader | |
Object Serialization | – | ObjectIntputStream、ObjectOutputStream |
Data conversion | – | DataIntputStream、DataOutputStream |
Counting | LineNumberReader | LineNumberInputStream |
Peeking ahead | PusbackReader | PushbackInputStream |
Printing | PrintWriter | PrintStream |
缓冲流
缓冲流要“套接”在相应的节点流上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法
J2SDK提供了四中缓冲流,其常用的构造方法为
BufferedReader(Read in)
BufferedReader(Read in, int sz) sz为自定义缓存区的大小
BufferedWriter (Write out)
BufferedWriter (Write out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size)
- 缓冲输入流支持其父类的mark和reset方法
- BufferedReader提供了readLine()方法用于读一行字符串(以\r或者\n分隔)
- BufferedWriter提供了newLine()方法用于写入一行分隔符
- 对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush方法将会使内存中的数据立刻写出
BufferedReader、BufferedWriter举例
public class TestBuffered {
public static void main(String[] args) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\java\\File\\Hello.java"));
BufferedReader br = new BufferedReader(new FileReader("d:\\java\\File\\Hello.java"));
String s = null;
//向文件中写了100行0~1的随机数
for(int i = 0;i<100;i++){
s = String.valueOf(Math.random());
bw.write(s);
bw.newLine();
}
bw.flush();
//打印数据
while((s=br.readLine()) != null){
System.out.println(s);
}
//关闭流
bw.close();
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//运行结果不再给出
}
}
}
转换流
InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换
InputStreamReader需要和InputStream“套接”
OutputStreamWriter需要和OutputStream“套接”
并且转换流在构造时可以指定其编码集合,例如:
InputStream isr = new InputStreamReader(System.in,”ISO8859_1”)
InputStreamReader、OutputStreamWriter举例
public class TestTransform {
public static void main(String[] args) {
try {
//FileOutputStream的构造方法中后又一个true,添加上代表文件中内容不会被覆盖而是添加
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\java\\File\\Hello.java",true),"ISO8859_1");
osw.write("123456789");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//System.in是标准的输入流,是InputStream的一个子类,完成了转换
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = null;
try {
while((s = br.readLine()) !=null){
if (s.equalsIgnoreCase("exit"))
break;
System.out.println(s.toUpperCase());
}
isr.close();
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
数据流
DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流,分别需要“套接”在InputStream和OutputStream类型的节点流上
DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据(如int、double等)的方法
DataInputStream和DataOutputStream的构造方法:
DataInputStream (InputStream in)
DataOutputStream (OUtputStream out)
数据流举例:
import java.io.*;
public class TestDataIO {
public static void main(String[] args) {
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());
dos.close();
dis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
9
0.20684497834468674
true
Print流
PrintWriter和PrintStream都属于流分别针对字符和字节
PrintWriter和PrintStream提供了重载的print、println方法用于多种数据类型的输出
PrintWriter和PrintStream输出操作不会抛出异常,用户通过检测错误状态获取错误信息
PrintWriter和PrintStream有自动的flush功能
PrintWriter常用方法
PrintWriter(Write out)
PrintWriter(Write out,boolean autoFlush)
PrintWriter(OutputStream out)
PrintWriter(OutprintStream out,boolean autoFlush)
PrintStream(OutprintStream out)
PrintStream(OutprintStream out,boolean autoFlush)
Print流举例
import java.io.*;
import java.util.Date;
public class TestPrintStream {
public static void main(String[] args) {
String s = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
FileWriter fw = new FileWriter("d:\\java\\File\\TestPrintStream.txt",true);
PrintWriter log = new PrintWriter(fw);
while((s=br.readLine()) != null){
if(s.equalsIgnoreCase("exit"))
break;
System.out.println(s.toUpperCase());
log.println("-------------");
log.println(s.toUpperCase());
//可以显式的调用
log.flush();
}
log.println("===="+new Date()+"=====");
log.flush();
log.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Object流
直接将Object写入或读出
transient关键字
serializable接口
externalizable接口 自身控制序列化过程,是serializable的一个子接口
Object流举例:
import java.io.*;
public class TestObjectIO {
public static void main(String[] args) throws Exception {
T t = new T();
t.j = 12;
FileOutputStream fos = new FileOutputStream("d:\\java\\File\\a.java");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(t);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("d:\\java\\File\\a.java");
ObjectInputStream ois = new ObjectInputStream(fis);
T tRead = (T) ois.readObject();
System.out.println(tRead.i + " " + tRead.j + " " + tRead.k + " "
+ tRead.b);
}
}
class T implements Serializable{
int i = 8;
int j = 15;
//加上transient关键字后在序列化时不于考虑,序列化时不会往硬盘上写
transient int k = 10;
double b = 2.3;
}
运行结果8 12 0 2.3