听到流这个词,我想很多人都会想到溪流,夏天的时候溪流清澈,蔚蓝的天空,一阵阵轻风吹过伴随着淙淙的流水声。但在编程里流的定义可没有这么美好,里面说流是一串连续不断的数据的集合。是不是一下子打断你美好的想像。
流分为很多种,例如有文件流、缓冲流、数据流。但不管是什么样的流,他们的本质还是流。 有很多人都这么比喻过,流就像水管里的水流,数据从一端流向另一端。文件流,数据流……。就好像不同的管子,有的管子是用来装文件的,有的管子是用来装数据的,也有的管子是套在另一个管子之上的,例如缓冲流。
Java.IO包中定义了很多类型的流。按数据流的方向不同可以分为输入流和输出流,按处理数据单位的不同可以分类字节流和字符流。按照功能不同可以分为节点流和处理流。
字节流 | 字符流 | |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
一、字节流
继承自InputStream的流都是输入流,继承自OutputStream的都是输出流,且他们的数据单位为字节(8bit),如下图:
FileInputStream Example
import java.io.FileInputStream;
public class vvv {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("c:\\data1.txt");
int b = 0;
long num = 0;
while ((b = fis.read()) != -1) {
System.out.print((char) b);
num++;
}
fis.close();
System.out.println("\n共读取了" + num + "个字节的字符\n");
}
}
FileOutputStream Example
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class vvv {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("c:\\data1.txt");
FileOutputStream fos = new FileOutputStream("c:\\data2.txt");
int b = 0;
while ((b = fis.read()) != -1) {
fos.write(b);
}
fis.close();
fos.close();
System.out.println("执行完毕");
}
}
二、字符流
继承自Reader的流都是输入流,继承自Writer的都是输出流,且他们的数据单位为字符(16bit),如下图
![]() | ![]() |
FileWriter Example
import java.io.FileReader; public class vvv { public static void main(String[] args) throws Exception { FileReader fr = new FileReader("c:\\data1.txt"); int b =0; while((b=fr.read())!=-1){ System.out.print((char)b); } } }
FileReader Example
import java.io.FileReader; import java.io.FileWriter; public class vvv { public static void main(String[] args) throws Exception { FileReader fr = new FileReader("c:\\data1.txt"); FileWriter fw = new FileWriter("c:\\data2.txt",true); //后面加一个参数true后,可以追加内容 int b =0; while((b=fr.read())!=-1){ fw.write(b); } fr.close(); fw.close(); System.out.println("执行完毕!"); } }
三、缓冲流
缓冲流要”嵌套”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的之法。
J2DK提供了四种缓冲流。缓冲输入流支持其父类的MARK和RESET方法。
BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔)
BufferedWriter提供了newLine用于写入一个行分隔符
对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出。
BufferReader Example
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class vvv {
public static void main(String[] args) throws Exception {
FileReader fReader = new FileReader("c:\\data1.txt");
BufferedReader br = new BufferedReader(fReader);
FileWriter fWriter = new FileWriter("c:\\data2.txt");
BufferedWriter bw = new BufferedWriter(fWriter);
String s = null;
while((s=br.readLine())!=null){
bw.write(s);
bw.newLine();//写完一行需要新起一行!
}
bw.flush();
bw.close();
br.close();
System.out.println("执行完成!");
}
}
四、转换流
InputStreamReader和OutputStreamWriter用字节数据转换成字符数据。InputStreamReader需要和InputStream套接。OutputStreamWriter需要和OutputStream套接。
Examlpe:
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
public class vvv {
public static void main(String[] args) throws Exception {
//将字节流转换成字符流
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("c:\\data1.txt",true) //注意后面的true,往原内容进行追加
);
//System.out.println(osw.getEncoding());
osw.write("Heelo OutputStreamWriter");
osw.close();
}
}
五、数据流
DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流。需要分别”嵌套”在InputStream和OutputStream类型的节点流上。DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据,例如int,double类型。DataInputStream和DataOutputStream的构造方法:
DataInputStream(InputStream in);
DataOutputStream(OutputStream out);
另外DataInputStream有readUTF, 而DataOutputStream有WriteUTF。这两个方法在网络编程TCP里非常好用。
Example:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class vvv {
public static void main(String[] args) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeDouble(0.6765451);
dos.writeBoolean(true);
//读取来
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
}
}
六、对象流
可以将对象序列化到一个文件中,使用的时候可以取出来使用。所以对需要进行序列化的对象类需要实现接口Serializeable
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class vvv {
public static void main(String[] args) throws Exception {
Goods good = new Goods("电脑",3012.1);
//写出一个对象到C盘a.txt文件中
FileOutputStream fileOut = new FileOutputStream("c:\\a.txt");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(good);
//把对象输出出来
FileInputStream fileInput = new FileInputStream("c:\\a.txt");
ObjectInputStream objectInput = new ObjectInputStream(fileInput);
Goods good2 = (Goods) objectInput.readObject();
System.out.println(good2.getName() + ":" + good2.getPrice());
}
}
class Goods implements Serializable {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
String name = null;
double price;
Goods(String name, double price) {
this.name = name;
this.price = price;
}
}