今日小雪:雨凝為雪,地氣凍結
記憶體與儲存裝置之間傳輸資料的通道
流的分類
按方向分:
-
輸入流:將<儲存裝置>中的內容讀入到<記憶體>中
-
輸出流:將<記憶體中的內容寫入到<儲存裝置>中
按單位分:
-
位元組流:以位元組為單位,可以讀寫所有資料
-
按功能分:
-
節點流:具有實際傳輸資料的讀寫功能
-
過濾流:在節點流的基礎上增強功能
位元組流
位元組流的父類(抽象類)
-
InputStream:位元組輸入流
-
public int read(){}
-
public int read(byte[] b){}
-
public int read(byte[] b, int off, int len){}
-
-
OutputSream:位元組輸出流
-
public void write(int n){}
-
public void write(byte[] b){}
-
public void write(byte[] b, int off, int len){}
-
檔案位元組流
-
FileInputStream:
-
public int read(byte[] b) //從流中讀取多個位元組,將讀到內容存入b陣列,返回實際讀到的位元組數;如果到達檔案尾部,則返回-1
public class Demo1 {
public static void main(String[] args) throws Exception{
//1 建立FileInputStream,並指定檔案路徑
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
//2 讀取檔案
//2.1 單個位元組讀取
int data = 0;
while((data = fis.read())!=-1){
System.out.println((char)data);
}
//2.2 多個位元組讀取
byte[] buf = new byte[1024];
int count = 0;
while ((count = fis.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
//3 關閉
fis.close();
}
} -
-
FileOutputSream:
-
public void write(byte[] b) //一次寫入多個位元組,將b陣列中所有位元組,寫入輸出流
public class Demo1 {
public static void main(String[] args) throws Exception {
//1 建立FileOutputStream,並指定檔案路徑
FileOutputStream fos = new FileOutputStream("d:\\aaa.txt",true);
//true則表示檔案可以繼續寫而不會被覆蓋,預設為false
//2 寫入檔案
fos.write(97);
fos.write('b');
fos.write('c');
String string = "helloworld";
fos.write(string.getBytes());
//3 關閉
fos.close();
}
} -
檔案複製(案例)
public class Demo1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\001.jpg");
FileOutputStream fos = new FileOutputStream("d:\\002.jpg");
byte[] buf = new byte[1024];
int count = 0;
while ((count=fis.read(buf))!=-1){
fos.write(buf,0,count);
}
fos.close();
fis.close();
}
}
位元組緩衝流
-
緩衝流:BufferedInputStream/BufferedOutputStream
-
提高IO效率,減少磁碟訪問次數
-
資料儲存在快取區中,flush是將快取區的內容寫入檔案中,也可以直接close
-
-
讀檔案
public class Demo1 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
int data = 0;
while ((data= bis.read())!=-1){
System.out.println((char)data);
}
//也可以自己建立一個快取區
byte[] buf = new byte[1024];
int count = 0;
while ((count = bis.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
bis.close();
}
}
-
寫檔案
public class Demo1 {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
for (int i = 0; i < 10; i++) {
bos.write("helloworld".getBytes());//寫入8K快取區
bos.flush();//重新整理到硬碟
}
//close內部會呼叫flush方法
bos.close();
}
}
物件流
物件流:ObjectInputStream/ObjectOutputStream
-
增強了緩衝區功能
-
增強了讀寫8種基本資料型別和字串功能
-
增強了讀寫物件的功能
-
readObject() 從流中讀取一個物件(反序列化)
-
writeObject(Object obj) 向流中寫入一個物件(序列化)
-
學生類
public class student implements Serializable {//實現Serializable介面
private String name;
private int age;
public student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
序列化
/**
* 要求:序列化的類必須要實現Serializable介面
*/
public class Demo1 {
public static void main(String[] args) throws Exception{
//1 建立物件流
FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2 序列化(寫入操作)
student zhangsan = new student("張三",20);
oos.writeObject(zhangsan);
//3 關閉
oos.close();
}
}
反序列化
public class Demo1 {
public static void main(String[] args) throws Exception {
//建立物件流
FileInputStream fis = new FileInputStream("d:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//讀取檔案
student s = (student) ois.readObject();
//關閉
ois.close();
System.out.println(s.toString());
}
}
序列化和反序列化注意事項
-
序列化的類必須要實現Serializable介面
-
序列化的類中的物件屬性也要求實現Serializable介面
-
serialVersionUID:序列化版本號ID,保證序列化的類和反序列化的類是同一個類
private static final long serialVersionUID = 100L;//這個數值是可以自定義的
-
使用transient(瞬間的)修飾屬性,這個屬性就不能被序列化
-
靜態屬性不能序列化
-
序列化多個物件時,可以藉助集合實現
public class Demo1 {
public static void main(String[] args) throws Exception {
//1 建立物件流
FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2 序列化(寫入操作)
student zhangsan = new student("張三", 20);
student lisi = new student("李四", 22);
// oos.writeObject(zhangsan);
// oos.writeObject(lisi);
ArrayList<student> list = new ArrayList<>();
list.add(zhangsan);
list.add(lisi);
oos.writeObject(list);
oos.close();
}
}
public class Demo2 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("d:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//讀取檔案
ArrayList<student> list = (ArrayList<student>) ois.readObject();
//關閉
ois.close();
System.out.println(list.toString());
}
}
字元流
常見的字元編碼
編碼方式和解碼方式不一樣時會出現亂碼
-
ISO-8859-1 包括ASCII 西歐 希臘語 泰語 阿拉伯語 希伯來語對應的文字元號(一個位元組,只能表示255個字元)
-
UTF-8 萬國碼(1/2/3個位元組表示)
-
GB2312 簡體中文(1/2個位元組表示)
-
GBK 簡體中文,擴充(1/2個位元組表示)
-
BIG5 臺灣,繁體中文
字元流的父類(抽象類)
-
Reader:字元輸入流
-
public int read(){}
-
public int read(char[] c){}
-
public int read(char[] c, int off, int len){}
-
-
Writer:字元輸出流
-
public void write(int n){}
-
public void write(String str){}
-
public void write(char[] c){}
-
檔案字元流
-
FileReader:
-
public int read(char[] c) //從流中讀取多個字元,將讀到內容存入c陣列,返回實際讀到的字元數;如果到達檔案尾部,則返回-1
-
public class Demo1 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:\\hello.txt");
//單個字元讀取
int data=0;
while ((data=fr.read())!=-1){
System.out.print((char) data);
}
//自建快取區,一次性讀取
char[] buf = new char[1024];
int count = 0;
while ((count= fr.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
fr.close();
}
}
-
FileWriter:
-
public void write(String str) //一次寫入多個字元
-
public class Demo1 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("d:\\hello.txt");
//單個字元讀取
for (int i = 0; i < 10; i++) {
fw.write("Java是世界上最好的語言\r\n");
fw.flush();
}
fw.close();
}
}
使用FileReader和FileWriter只能複製文字檔案,不能複製圖片或者二進位制檔案
因為圖片和二進位制檔案沒有字元編碼
字元緩衝流
-
緩衝流:BufferedReader/BufferedWriter
-
優點
-
高效讀寫
-
支援輸入換行符
-
可一次寫一行,讀一行
-
-
BufferedReader
public class Demo1 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:\\write.txt");
BufferedReader br = new BufferedReader(fr);
//一行一行讀
String line = null;
while ((line = br.readLine())!=null){
System.out.println((line);
}
//可以自己建立一個快取區
char[] buf = new char[1024];
int count = 0;
while ((count = br.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
br.close();
}
}
-
BufferedWriter
public class Demo1 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("d:\\write.txt");
BufferedWriter bw = new BufferedWriter(fw);
for (int i = 0; i < 10; i++) {
bw.write("好好學習,天天向上");
bw.newLine();//寫入一個換行符(每個系統的換行符不一樣,但這個方法均適配)
bw.flush();
}
bw.close();
}
}
列印流
-
PrintWriter:
-
封裝了print()/println()方法,支援寫入後換行
-
支援資料原樣列印
-
public class Demo1 {
public static void main(String[] args) throws Exception {
PrintWriter pw = new PrintWriter("d:\\print.txt");
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');
pw.close();
}
}
轉換流
-
橋轉換流:InputStreamReader/OutputStreamWriter
-
可將位元組流轉換為字元流
-
可設定字元的編碼方式
-
-
InputStreamReader
public class Demo1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\writer.txt");
InputStreamReader irs = new InputStreamReader(fis,"utf-8");
int data = 0;
while ((data = irs.read())!=-1){
System.out.print((char)data);
}
irs.close();
}
}
-
OutputStreamWriter
public class Demo1 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("d:\\info.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
for (int i = 0; i < 10; i++) {
osw.write("我愛川農\r\n");
osw.flush();
}
osw.close();
}
}