Ø Java.io包中定義了多個流類型(類或抽象類)來實現輸入/輸出功能;可以從不同
的角度對其進行分類:
l 按數據流的方向不同可以分爲輸入流和輸出流(站在程序角度而言);
l 按處理數據單位不同可以分爲字節流和字符流;
l 按功能不同可以分爲節點流和處理流。
Ø J2SDK 所提供的所有流類型位於java.io內部都分別繼承自以下四種抽象流類
型。
|
字節流 |
字符流 |
輸入流 |
InputStream(字節8bit) |
Reader(字符,2個字節) |
輸出流 |
OutputStream |
Writer |
說明:節點流爲可以從一個特定的數據源(節點)讀寫數據; 處理流是”連接”在已存在的流(節點流或處理流)之上,通過對數據的處理爲程序提供更爲強大的讀寫功能。
Ø 繼承自InputStream的流都是用於向程序中輸入數據,數據單位爲字節(8bit)
InputStream基本方法:
Ø 繼承自OutputStream的流都是用於向程序中輸出數據,數據單位爲字節(8bit)
OutputStream的基本方法:
說明:良好的編程習慣是在close數據流之前先調用flush()方法將緩衝區的數據全部先寫到目的地。
Ø 繼承自Reader的流都是用於向程序中輸入數據,數據單位爲字符(16bit)
Reader的基本方法:
Ø 繼承自Writer的流都是用於向程序中輸出數據,數據單位爲字符(16bit)
Writer的基本方法:
Ø 節點流類型
Ø 測試FileInputStream
public class TestFileInput {
public static void main(String[] args) {
int b;
long num = 0;
try {
FileInputStream fis = new FileInputStream
("D://java+必備軟件//java//01//ToString.java");
while((b=fis.read()) != -1) {//讀完後會自動指向下一個字節數據
System.out.print((char)b);
//得到的b的值爲字符對應的ASCII碼,現在將b強制轉換成字符類型
num ++;
}
fis.close();
System.out.println();
System.out.println("共讀取了" + num + "個字節");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
說明:Window下的文件分隔符除了使用上述的”//”外,還可以使用”/”
Ø 測試FileOutputStream
public class TestFileOutput {
public static void main(String[] args) {
int b;
long num = 0;
try {
FileInputStream fis = new FileInputStream
("D://java+必備軟件//java//01//Cat.java");
//輸出流在文件不存在的情況下會自動創建,但不會自動創建文件夾。
FileOutputStream fos = new FileOutputStream
("D://java+必備軟件//java//01//Cat11.java");
while((b=fis.read())!=-1) {//-1爲讀到文件結尾
fos.write(b);
num ++;
}
fis.close();
fos.close();
System.out.println();
System.out.println("共讀取了" + num + "個字節");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
說明:上述的Stream不會得到中文,因爲他們是按照字節單位讀取的,要想打印出中文,必須使用Writer、Reader
Ø 測試FileReader(可以讀取到中文)
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TestFileReader {
public static void main(String[] args) {
int b;
try {
FileReader fr = new FileReader
("D://java+必備軟件//java//16//ExTest.java");
while((b=fr.read()) != -1) {
System.out.print((char)b);
}
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Ø 測試FileWriter(可以寫入中文)
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestFielWriter {
public static void main(String[] args) {
int b;
try {
FileReader fr = new FileReader
("D://java+必備軟件//java//16//ExTest.java");
FileWriter fw = new FileWriter
("D://java+必備軟件//java//16//ExTest1.java");
while((b=fr.read()) != -1) {
fw.write(b);
}
fr.close();
fw.close();
System.out.println("文件複製完畢!");
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("找不到指定文件!");
} catch(IOException e) {
e.printStackTrace();
System.out.println("輸入輸出錯誤!");
}
}
}
Ø 處理流類型
Ø 緩衝流
Ø 測試BufferedInputStream
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestBufferStream {
public static void main(String[] args) {
int b;
try {
FileInputStream fis = new FileInputStream
("D://java+必備軟件//java//16//ExTest.java");
BufferedInputStream bis = new BufferedInputStream(fis);
System.out.println(bis.markSupported());
//並不是所有的stream都支持mark()方法,該語句可以進行查看是否支持。
bis.mark(20);
//在當前位置做標誌,參數20爲在標誌位置失效前可以讀取字節的最大限制
//不要理解成在第20個字符位置做標誌
bis.skip(20);//跳過20個字符,即在第21個字符位置開始讀取
System.out.println("NO.1-----------------");
for(int i=0; i<20 && (b=bis.read())!=-1; i++) {
System.out.print((char)b);
}
bis.reset();//回到前面標誌mark的位置
System.out.println();
System.out.println("NO.2-----------------");
for(int i=0; i<20 && (b=bis.read())!=-1; i++) {
System.out.print((char)b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
輸出實例(中間正好遇到回車(13)換行(10)符):
true
NO.1-----------------
class MyException
NO.2-----------------
import java.util.*;
Ø 測試BufferedWriter、BufferedReader
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestBufferWriter {
public static void main(String[] args) {
String s;
try {
BufferedWriter bw = new BufferedWriter
(new FileWriter("D://java+必備軟件//java//16//data1.txt"));
BufferedReader br = new BufferedReader
(new FileReader("D://java+必備軟件//java//16//data1.txt"));
for(int i=0; i<10; i++) {
bw.write(String.valueOf(Math.random()));
bw.newLine();//寫入一換行
}
bw.write("愛的翅膀");//寫入中文
bw.flush();
while((s=br.readLine())!=null) {
//讀取一行,該stream擁有的很好的一種使用方法
System.out.println(s);
}
bw.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ø 轉換流
l InputStreamReader和OutputStreamWriter用於字節數據到字符數據的轉換;
l InputStreamReader需要和InputStream”套接”;
l OutputStreamWriter需要和OutputStream”套接”;
l 轉換流在構造時可以指定其編碼集合,例如:
InputStreamReader isr = new InputStreamReader(System.in, “ISO8859-1”);
Ø 測試OutputStreamWriter(必須調用flush()方法才能將數據寫入)
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TestOutputStreamWriter {
public static void main(String[] args) {
int b;
try {
OutputStreamWriter osw = new OutputStreamWriter
(new FileOutputStream("D://java+必備軟件//java//16//data1.txt"));
osw.write("Hello -- 你好!");//可以直接寫字符串
osw.flush();//必須調用flush()方法才能將數據寫到文件中
System.out.println(osw.getEncoding());//默認爲BGK
BufferedReader br = new BufferedReader
(new FileReader("D://java+必備軟件//java//16//data1.txt"));
System.out.println(br.readLine());//讀取一行
FileReader fr = new FileReader
("D://java+必備軟件//java//16//data1.txt");
while((b=fr.read())!=-1) {
System.out.print((char)b);
}
System.out.println();
//參數true表示追加數據,而不是覆蓋,”ISO8859-1”是指定的編碼,西方語言集合
osw = new OutputStreamWriter(new FileOutputStream
("D://java+必備軟件//java//16//data1.txt", true), "ISO8859-1");
osw.write("我也好!");
osw.flush();//必須調用flush()方法才能將數據寫到文件中
System.out.println(br.readLine());
System.out.println(osw.getEncoding());
osw.close();
br.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
打印結果:
GBK
Hello -- 你好!
Hello -- 你好!
????
ISO8859_1
Ø 測試InputStreamReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestInputStreamReader {
public static void main(String[] args) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
String strin = br.readLine();//阻塞式的方法
while(!strin.equalsIgnoreCase("exit")) {
System.out.println(strin.toUpperCase());
strin = br.readLine();
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
說明:System.in指的是連通Console的一個InputStream,通過這條Stream我們就可以讀取輸入到命令框的值了。同理,存在System.out
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TestSystemout {
public static void main(String[] args) {
OutputStreamWriter osw = new OutputStreamWriter(System.out);
try {
//將值輸出到Console框,作用相當於System.out.println(“…”);
osw.write("您好!");
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ø 數據流
Ø 測試DataInputStream和DataOutputStream
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestDataStream1 {
public static void main(String[] args) {
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("D://java+必備軟件//java//16//data1.txt"));
dos.writeDouble(23);
dos.writeUTF("您好");
dos.writeBoolean(true);
DataInputStream dis = new DataInputStream(new FileInputStream("D://java+必備軟件//java//16//data1.txt"));
System.out.println(dis.readDouble());
System.out.println(dis.readUTF());
System.out.println(dis.readBoolean());
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:寫入文件data1.txt的數據並不是像寫入的那樣,但是由DataOutputStream讀出顯示的數據就是原來輸入的數據。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class TestDataStream {
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) {
e.printStackTrace();
}
}
}
打印結果:
9
0.17502217440874912
True
Ø Print流
Ø 測試PrintStream
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class TestPrintStream {
public static void main(String[] args) {
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream
("D://java+必備軟件//java//16//data1.txt");
ps = new PrintStream(fos);
} catch(IOException e) {
e.printStackTrace();
}
if(ps != null) {
System.setOut(ps);//將System.out的輸出對象改變了
}
int ln = 0;
for(char c=0; c<=60000; c++) {
System.out.print(c + "");//將不再輸出到console窗口
if(ln++ >= 100) {
System.out.println();
ln = 0;
}
}
}
}
Ø Object流
直接將Object寫入或讀出(該Object必須先實現serializable/序列化接口,該接
口沒有任何實現的方法,屬於標誌性接口)
ü 測試ObjectOutputStream、ObjectInputStream
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TestObjectStream {
public static void main(String[] args) {
T t = new T();
t.k = 8;
try {
FileOutputStream fos = new FileOutputStream
("D://java+必備軟件//java//16//data1.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(t);//直接寫入對象
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream
("D://java+必備軟件//java//16//data1.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
T tReaded = (T)ois.readObject();
System.out.println
(tReaded.i + " " + tReaded.j + " " + tReaded.d + " " + tReaded.k);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class T implements Serializable {
int i = 10;
int j = 9;
double d = 2.3;
int k = 23;
}
打印結果:10 9 2.3 8
注意1:如果類中某個值在序列化的時候不想予以考慮,可以使用transient關鍵字,如:transient int k = 23;則此時打印結果爲:10 9 2.3 0
注意2:serializable接口只將對象進行了序列化,但是具體是如何序列化的用戶不清楚,爲了實現用戶能夠自己進行序列化,提供了externalizable接口,裏面主要有兩個方法:
void readExternal(ObjectInput in)
void writeExternal(ObjectOutput out)