风萧萧兮易水寒,串流一去兮不复还

I/O 以连接的节点(Node)、传送的资料型态、以及输入/输出来区分

分作以下类别(Class)

档案
记忆体
Pipe
 X  位元组(Byte)传输
字元(char)传输
字串(String)传输
 X 
输入
输出

通常做位元组传输,会叫做Stream

以常见的字串传输,会叫做Reader/Writer

举例来说,FileInputStream是做档案位元输入的类别;InputStreamReader是做字串输入的类别

Pipe是比较特殊的用途,搭配在多执行续上使用,参照PipedInputStreamPipedOutputStream

字串处理的I/O被分离在ReaderWriter类别底下

其他的都直接继承了InputStreamOutputStream

 

不论是哪一种传输,都是以节点(Node)做为起点或终点,做出Stream这样的动作

Stream就如同字面上的意思,像水流一样,有开有关

当Read()或write()方法被呼叫时,串流就会开启,直到close()被呼叫为止

有时候串流会有保护同时只开放一个程序使用,因此必须记得close()串流,避免其他程序无法使用

 

在文章的第一行就有提到,串流是无法回头的

当一直Read()资料时,串流就一点一点的流去,不会回头

不过如果一定要让流过的串流再回头看一次,就要使用一些Buffer的方式,先把串流存起来,就像是蓄水槽一样

JAVA也有提供一些搭配使用的缓冲区类别,等一下会说到

 

通常我们会用到的串流,就是以档案为节点的串流了,读写档案都用的到

使用的方法十分简单,只需要开档后,建立起Stream的物件,在使用读写的方法就可以了

✎ 记事本                      _  ❒   1.在想要的目录中建立一个文字档
This is a test...



import java.io.*;

public class Test {
public static void main(String[] args) {
FileInputStream fin;
try {
fin = new FileInputStream("c:\\file.txt");
while (fin.available() > 0)
System.out.print(fin.read());
} catch (IOException e) {
e.printStackTrace();
}
}
}


 2.使用程式码来读档
◙ C:\Windows\System32\cmd.exe         _  ❒ 
 3.执行的结果,很容易吧
This is a test...


前面有提到,FileInputStream他是以Byte为传输单位

而英文字母和一般标点符号长度也恰好是一个Byte,因此显示出来都很正常

不过如果读写中文时就会出问题了

✎ 记事本                     _  ❒   1.这次的内容是中文
中文测试




◙ C:\Windows\System32\cmd.exe        _  ❒ 
 2.执行结果
出现了世界末日的日期 (误
164164164229180250184213



如果想要顺利的读取中文,又想坚持使用FileInputStream的话,就要用到Byte[] 来做buffer,而且阵列大小必须是2的倍数,因为中文字占2个Byte


import java.io.*;


public class Test {
public static void main(String[] args) {
FileInputStream fin;
try {
fin = new FileInputStream("c:\\file.txt");
byte buf[] = new byte[8];//建立一个大小8Byte的缓冲区
int bufSize;//用来计算读入的资料大小
while (fin.available() > 0)
bufSize = fin.read(buf);//读取资料到buf内
System.out.print(new String(buf, 0, bufSize));

} catch (IOException e) {
e.printStackTrace();
}
}
}


 1.修改一些程式码
◙ C:\Windows\System32\cmd.exe        _  ❒ 
        2.出现了正确的结果
中文测试



不过要是中文字中间夹杂了1Byte大小的字元,读取就会错乱,这时候就没有办法再坚持使用FileInputStream了

FileReader就登场了!


import java.io.*;


public class Test {
public static void main(String[] args) {
FileReader fin;
try {
fin = new FileReader("c:\\file.txt");
int word;
while (fin.ready()){
word = fin.read();
System.out.print((char)word);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

跟FileInputStream几乎是一样的用法

FileReader或FileWriter都是以字元做传输的单位,因此不管是中文还是英文,都可以正常的传输

 

到这里为止,我们知道要如何读写档案文字

但是如果我们要读写的是数字、浮点数甚至是物件呢?

当然你可以把123或者0.01还有其他资料用String的方式写到档案中,就像刚才那样

不过如此写入的话,取出时,还要做字串分析等等繁杂的工作

虽然不是不可以,但是程式就不漂亮了

那么,该如何把真正的"资料型态"写到档案里面呢?

我们需要一些转接头,把资料型态与串流做个连结,称作chain

为了达到串流连结,我们要用到一些的类别,也就是转接头,称作Filter

Filter除了可以达到转换型态的功能外,还有些具有缓冲的功能,也就是让流去的串流可以被回朔

来看看JAVA提供那些Filter的类别

串流缓冲区 BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter

物件串流 ObjectInputStream
ObjectOutputStream
基本资料型态串流 InputStreamReader
InputStreamWriter
DataInputStream
DataOutputStream

计算行数 LineNumberInputStream
LineNumberReader
堆叠串流 PushbackInputStream
PushbackReader
列印串流 PrintStream
PrintWriter
蓝色的比较常用喔

 

这么多种类转接头,看到都晕了…

不过常用的也不会很多,拿比较常用的DataOutputStream举例吧

DataOutputStream可以将输出的资料转换成各种基本资料型态:int, char, double, float...等等

要怎么转呢?看看↓


import java.io.*;


public class Test {
public static void main(String[] args) {
FileOutputStream fin;
try {
fin = new FileOutputStream("c:\\file.txt");
DataOutputStream dataWrite = new DataOutputStream(fin);
short sh[] = {1,2,3,4,5};
for(short i : sh){
dataWrite.writeShort(i);//这里的方法要搭配资料型态使用
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

这样就完成了写入short资料型态的数字到档案里了,当然也可以用类似方式写入整数、浮点数等等…

不过当好奇的用记事本打开档案一看…奇怪,啥都没有啊!

那是当然的了,因为那不是以"字串"的编码写入,而是以你指定的资料编码写入(上面例子就是short)

而记事本只会把资料以字串的编码来呈现,其中字串编码又分ASCII、UTF…数种

不过当你再写一段以short读入资料的程式之后,你就可以直接用short的变数来接收读入的资料了

超方便的!

 

刚才有提到,除了基本资料型态之外,物件也可以存进档案中

不过存进去的只限于"资料",也就是物件中的"属性(attribute)"

物件中的方法(method)是不会被存的

物件在要被丢到串流中之前,必须先序列化(Serialization),序列化其实也不是甚么很神秘的东西,只是把资料从物件中抽出来准备传送而已,这个部分电脑会帮你完成,你只需要在你想要被传送的类别上,implements Serializable就可以了

用到的Filter类别是ObjectInputStream、ObjectOutputStream,用法跟基本资料型态的一样,把FileOutputStream的物件挂上去(传入建构子)就可以了

同样的,读取物件时,用该物件来接收,你就可以得到之前存起来的物件了

相关文章