首先我們需要知道什麼是流?
流就是一組有順序的,有起點和終點的字節集合,是對數據傳輸的總稱或抽象。它的特性是進行數據傳輸。
接下來我們看看IO流的分類:
- 按流向分類:輸入流、輸出流
- 按操作對象分類:字節流、字符流
- 按功能分類:節點流、處理流
前方高能,坐下來請慢慢地聽我說!
一:字節流和字符流
字節流:InputStream 和OutputStream 是java中可以按照最小字節單位讀取的流,即每次讀寫一個字節,字節流是直接連接到輸入源的流。
字符流:是以字符爲單位進行數據處理的IO流。本質其實就是基於字節流讀取時,去查找指定的碼錶。
二:字節流與字符流之間的區別:
- 讀寫單位不同:字節流式以字節(8位2進制)爲單位,字符流是以字符爲單位,根據碼錶映射字符,一次可能讀多個字節。
- 處理對象不同:字節流能處理所有類型的數據(如圖片、avi等),而字符流只能處理字符類型的數據。
- 一次讀入或讀出是8位二進制。
- 字符流:一次讀入或讀出是16位二進制。
結論:
Out—>將輸出的字符流—>字節流—>用於輸出到控制檯 或者 文件
注意這個是寫====輸出的是來源,形容詞,不是你理解的字符輸出流轉字節輸出流
In—>將輸入的字節流—>字符流—>用於讀取到控制檯 或 內存
注意這個是讀====輸入的是來源,形容詞,不是你理解的字節輸入流轉字符輸入流
要麼字節流要麼字符流,具體再分哪種來源的流的話,就看是In還是Out了
- InputStreamReader看似是往裏寫(In),其實是往外讀(Reader)
- OutputStreamWriter看似是往外讀(Out),其實是往裏寫(Writer)
三:輸入流和輸出流的用途:
- 輸入流是指程序從數據源中讀取數據。只進行讀操作;
- 輸出流是指將數據從程序中寫到指定的文件中;
四:輸入流字節流InputStream與輸出字節流InputStream
- InputStream是一個抽象類,是所有輸入字節流的父類。
- ByteArrayInputStream、StringBufferInputStream、FileInputStream
他們分別從數組、StringBuffer、和本地文件中讀取數據。 - PipedInputStream是從與其它線程共用的管道中讀取數據,與Piped 相關的知識後續單獨介紹。
- ObjectInputStream 和所有FilterInputStream 的子類都是裝飾流(裝飾器模式的主角)。
- OutputStream 是所有的輸出字節流的父類,它是一個抽象類。
- ByteArrayOutputStream、FileOutputStream 是兩種基本的介質流,它們分別向Byte數組、和本地文件中寫入數據。
- PipedOutputStream 是向與其它線程共用的管道中寫入數據。
- ObjectOutputStream 和所有FilterOutputStream 的子類都是裝飾流。
上代碼理解一下,此代碼使用緩衝數組的方法讀取文件內容,提高效率
public static void readArr() {
// 1、明確源數據源
File f = new File("F:/1/菜丸子/1.txt");
// 2、構建流的對象
InputStream ins = null;
try {
ins = new FileInputStream(f);
// 3、聲明緩衝數組
int i;// 表示讀取了多少個字符到數組中
byte[] bt = new byte[5];// 字節緩衝數組
// 4、讀取數據到數組中
//可以讀多少寫多少,轉化成char類型,但是文件中都是英文,如果有中文則輸出亂碼
while ((i = (ins.read(bt))) != -1) {
for (int j = 0; j < i; j++) {
System.out.print((char) bt[j]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//關閉流
try {
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
五:節點流和處理流的概念
節點流:直接與數據相連,進行數據的讀寫;
處理流:是指在節點流上套接了一層。
- 常用的節點流
1.文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件進行處理的節點流
import java.io.FileReader;
import java.io.FileWriter;
/**
* 使用FileRead、FileWriter複製文件
*
* @author caiwan
*
*/
public class TestFieldWriter {
public static void main(String []args){
FileReader fr=null;
FileWriter fw=null;
try {
fr=new FileReader("C:\\Users\\116060\\Desktop\\eeee.txt");//要讀取的文件
fw=new FileWriter("C:\\Users\\116060\\Desktop\\ffff.txt");//要複製的目的文件
int i=0;
while((i=fr.read())!=-1){
fw.write(i);
System.out.println((char)i);//將得到的ASCII碼值轉換成字符型
}
fr.close();
fw.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
2.數 組 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 對數組進行處理的節點流(對應的不再是文件,而是內存中的一個數組)
3.字符串 :StringReader、 StringWriter 對字符串進行處理的節點流
4.管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 對管道進行處理的節點流
- 常用的處理流
1.緩衝流:BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加緩衝功能,避免頻繁讀寫硬盤。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
/**
* 字符緩衝流(使用 BufferedReader 和 BufferedWriter)
*
* @author caiwan
*
*/
public class Demo2 {
public static void main(String[] args) {
// 1、指明源和目標
File o = new File("F:/temp/java11.template");
File t = new File("F:/temp/java11.txt");
// 2、構建流的對象
Reader re = null;
Writer wt = null;
BufferedReader bfr = null;
BufferedWriter bfw = null;
try {
re = new FileReader(o);
bfr = new BufferedReader(re);
wt = new FileWriter(t);
bfw = new BufferedWriter(wt);
String msg = null;
// 讀取操作
while ((msg = bfr.readLine()) != null) {// 讀一行
// System.out.println(msg);
bfw.write(msg);
bfw.write("\r\n");// 執行換行,讀一行 寫一行 換行
// 或者 :bfw.newLine();//換行
}
bfw.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關閉流
try {
if (wt != null) {// 爲了避免空指針異常,進行判空
wt.close();
}
if (re != null) {
re.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.轉換流:InputStreamReader 、OutputStreamReader實現字節流和字符流之間的轉換。
3.數據流: DataInputStream 、DataOutputStream 等-提供將基礎數據類型寫入到文件中,或者讀取出來。
六:轉換流
InputStreamReader 、OutputStreamWriter 要InputStream或OutputStream作爲參數,實現從字節流到字符流的轉換。
七:常用例子
包裝流設置字符集的案例:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Scanner;
/**
* 包裝流設置字符集,使用InputStreamReader 和 OUtputStreamWriter:
* @author caiwan
*/
public class Demo01 {
public static void main(String[] args) {
// 確定源和目標文件
Scanner sc = new Scanner(System.in);
File o = new File("kh/java48.template");
File t = new File("kh/java48.txt");
check(o);
check(t);
// 構建流對象
InputStream ins = null;
OutputStream outs = null;
InputStreamReader insr = null;
OutputStreamWriter outsw = null;
try {
outs = new FileOutputStream(o);// 先做爲目標文件寫入內容
outsw = new OutputStreamWriter(outs, "UTF-8");//編碼格式爲UTF-8
System.out.println("輸入你要寫入的內容:");
String msg = sc.next();
// 寫入內容
outsw.write(msg);
// 刷新
outsw.flush();
System.out.println("已經完全寫入!");
ins = new FileInputStream(o);// 作爲源文件
insr = new InputStreamReader(ins, "UTF-8");//編碼格式爲UTF-8
outs = new FileOutputStream(t);// 作爲寫入的目標文件
outsw = new OutputStreamWriter(outs, "UTF-8");//編碼格式爲UTF-8
char[] ch = new char[1024];
int i = 0;
// 執行邊讀邊寫
while ((i = insr.read(ch)) != -1) {
outsw.write(ch, 0, i);
}
// 刷新
outsw.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關閉流
try {
if (outs != null) {
outs.close();
}
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void check(File file) {
try {
if (!file.exists()) {
file.getParentFile().mkdirs();// 創建文件夾
file.createNewFile();// 創建文件
System.out.println("沒有該文件!已創建成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
最後:
歡迎各位小夥伴關注我的公衆號:菜丸的程序屋。希望將我的不足之處給予指點,謝謝大家。喜歡Java,熱衷學習的小夥伴可以加我微信: CaiWan_Y