一舍沙、IO流概述
概述:
IO流簡單來說就是Input和Output流,IO流主要是用來處理設備之間的數(shù)據(jù)傳輸,Java對于數(shù)據(jù)的操作都是通過流實現(xiàn)撮珠,而java用于操作流的對象都在IO包中。
分類:
按操作數(shù)據(jù)分為:字節(jié)流和字符流金矛。 如:Reader和InputStream
按流向分:輸入流和輸出流芯急。如:InputStream和OutputStream
IO流常用的基類:
* InputStream , OutputStream
字符流的抽象基類:
* Reader 驶俊, Writer
字符流和字節(jié)流的區(qū)別:
- 1.字節(jié)流讀取的時候娶耍,讀到一個字節(jié)就返回一個字節(jié); 字符流使用了字節(jié)流讀到一個或多個字節(jié)(中文對應的字節(jié)數(shù)是兩個饼酿,在UTF-8碼表中是3個字節(jié))時榕酒。先去查指定的編碼表,將查到的字符返回故俐。
- 2.字節(jié)流可以處理所有類型數(shù)據(jù)奈应,如:圖片,MP3购披,AVI視頻文件杖挣,而字符流只能處理字符數(shù)據(jù)。只要是處理純文本數(shù)據(jù)刚陡,就要優(yōu)先考慮使用字符流惩妇,除此之外都用字節(jié)流株汉。
二、字符流
1. 字符流簡介:
- 字符流中的對象融合了編碼表歌殃,也就是系統(tǒng)默認的編碼表乔妈。我們的系統(tǒng)一般都是GBK編碼。
- 字符流只用來處理文本數(shù)據(jù)氓皱,字節(jié)流用來處理媒體數(shù)據(jù)路召。
- 數(shù)據(jù)最常見的表現(xiàn)方式是文件,字符流用于操作文件的子類一般是FileReader和FileWriter波材。
2.字符流讀寫:
注意事項:
寫入文件后必須要用flush()刷新股淡。
用完流后記得要關閉流
使用流對象要拋出IO異常
定義文件路徑時,可以用“/”或者“\”廷区。
在創(chuàng)建一個文件時唯灵,如果目錄下有同名文件將被覆蓋。
在讀取文件時隙轻,必須保證該文件已存在埠帕,否則出異常
示例1:在硬盤上創(chuàng)建一個文件,并寫入一些文字數(shù)據(jù)
class FireWriterDemo {
public static void main(String[] args) throws IOException { //需要對IO異常進行處理
//創(chuàng)建一個FileWriter對象,該對象一被初始化就必須要明確被操作的文件玖绿。
//而且該文件會被創(chuàng)建到指定目錄下敛瓷。如果該目錄有同名文件,那么該文件將被覆蓋斑匪。
FileWriter fw = new FileWriter("F:\\1.txt");//目的是明確數(shù)據(jù)要存放的目的地琐驴。
//調用write的方法將字符串寫到流中
fw.write("hello world!");
//刷新流對象緩沖中的數(shù)據(jù),將數(shù)據(jù)刷到目的地中
fw.flush();
//關閉流資源秤标,但是關閉之前會刷新一次內部緩沖中的數(shù)據(jù)绝淡。當我們結束輸入時候,必須close();
fw.write("first_test");
fw.close();
//flush和close的區(qū)別:flush刷新后可以繼續(xù)輸入苍姜,close刷新后不能繼續(xù)輸入牢酵。
}
}
代碼示例:把當前項目目錄下的a.txt內容復制到當前項目目錄下的b.txt中
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
// 封裝數(shù)據(jù)源
FileReader fr = new FileReader("a.txt");
// 封裝目的地
FileWriter fw = new FileWriter("b.txt");
// 一次一個字符
// int ch = 0;
// while ((ch = fr.read()) != -1) {
// fw.write(ch);
// }
// 一次一個字符數(shù)組
char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
fw.flush();
}
// 釋放資源
fw.close();
fr.close();
}
}
3.字符緩沖流
字符流為了高效讀寫,也提供了對應的字符緩沖流衙猪。BufferedWriter:字符緩沖輸出流馍乙,BufferedReader:字符緩沖輸入流。
BufferedWriter基本用法
將文本寫入字符輸出流垫释,緩沖各個字符丝格,從而提供單個字符、數(shù)組和字符串的高效寫入棵譬。 可以指定緩沖區(qū)的大小显蝌,或者接受默認的大小。在大多數(shù)情況下订咸,默認值就足夠大了曼尊。
代碼示例:BufferedWriter基本用法
/**
* 字符流為了高效讀寫酬诀,也提供了對應的字符緩沖流。
* BufferedWriter:字符緩沖輸出流
* BufferedReader:字符緩沖輸入流
*
* BufferedWriter:字符緩沖輸出流
* 將文本寫入字符輸出流骆撇,緩沖各個字符瞒御,從而提供單個字符、數(shù)組和字符串的高效寫入神郊。
* 可以指定緩沖區(qū)的大小肴裙,或者接受默認的大小。在大多數(shù)情況下涌乳,默認值就足夠大了蜻懦。
*/
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
// BufferedWriter(Writer out)
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
// new FileOutputStream("bw.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
bw.write("hello");
bw.write("world");
bw.write("java");
bw.flush();
bw.close();
}
}
BufferedReader基本用法
從字符輸入流中讀取文本,緩沖各個字符爷怀,從而實現(xiàn)字符阻肩、數(shù)組和行的高效讀取带欢。 可以指定緩沖區(qū)的大小运授,或者可使用默認的大小。大多數(shù)情況下乔煞,默認值就足夠大了吁朦。
代碼示例: BufferedReader基本用法
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建字符緩沖輸入流對象
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
// 方式1
// int ch = 0;
// while ((ch = br.read()) != -1) {
// System.out.print((char) ch);
// }
// 方式2
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 釋放資源
br.close();
}
}
特殊功能
- BufferedWriter,newLine():根據(jù)系統(tǒng)來決定換行符
- BufferedReader渡贾,String readLine():一次讀取一行數(shù)據(jù)
代碼示例:字符緩沖流的特殊方法
public class BufferedDemo {
public static void main(String[] args) throws IOException {
// write();
read();
}
private static void read() throws IOException {
// 創(chuàng)建字符緩沖輸入流對象
BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));
// public String readLine():一次讀取一行數(shù)據(jù)
// String line = br.readLine();
// System.out.println(line);
// line = br.readLine();
// System.out.println(line);
// 最終版代碼
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//釋放資源
br.close();
}
private static void write() throws IOException {
// 創(chuàng)建字符緩沖輸出流對象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
for (int x = 0; x < 10; x++) {
bw.write("hello" + x);
// bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.close();
}
}
代碼示例:字符緩沖流復制文本文件
/*
* 需求:把當前項目目錄下的a.txt內容復制到當前項目目錄下的b.txt中
*
* 數(shù)據(jù)源:
* a.txt -- 讀取數(shù)據(jù) -- 字符轉換流 -- InputStreamReader -- FileReader -- BufferedReader
* 目的地:
* b.txt -- 寫出數(shù)據(jù) -- 字符轉換流 -- OutputStreamWriter -- FileWriter -- BufferedWriter
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
// 封裝數(shù)據(jù)源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封裝目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
// 讀寫數(shù)據(jù)
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 釋放資源
bw.close();
br.close();
}
}
三逗宜、字節(jié)流
1.概述:
1、字節(jié)流和字符流的基本操作是相同的空骚,但是要想操作媒體流就需要用到字節(jié)流纺讲。
2、字節(jié)流因為操作的是字節(jié)囤屹,所以可以用來操作媒體文件熬甚。(媒體文件也是以字節(jié)存儲的)
3、讀寫字節(jié)流:InputStream 輸入流(讀)和OutputStream 輸出流(寫)
4肋坚、字節(jié)流操作可以不用刷新流操作乡括。
-
5、InputStream特有方法:
int available();//返回文件中的字節(jié)個數(shù)
注:可以利用此方法來指定讀取方式中傳入數(shù)組的長度智厌,從而省去循環(huán)判斷诲泌。但是如果文件較大,而虛擬機啟動分配的默認內存一般為64M铣鹏。當文件過大時敷扫,此數(shù)組長度所占內存空間就會溢出。所以诚卸,此方法慎用呻澜,當文件不大時递礼,可以使用。
1.字節(jié)流寫數(shù)據(jù)的方式
/*
* 字節(jié)輸出流操作步驟:
* A:創(chuàng)建字節(jié)輸出流對象
* B:調用write()方法
* C:釋放資源
*
* public void write(int b):寫一個字節(jié)
* public void write(byte[] b):寫一個字節(jié)數(shù)組
* public void write(byte[] b,int off,int len):寫一個字節(jié)數(shù)組的一部分
*/
public class FileOutputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 創(chuàng)建字節(jié)輸出流對象
// OutputStream os = new FileOutputStream("fos2.txt"); // 多態(tài)
FileOutputStream fos = new FileOutputStream("fos2.txt");
// 調用write()方法
//fos.write(97); //97 -- 底層二進制數(shù)據(jù) -- 通過記事本打開 -- 找97對應的字符值 -- a
// fos.write(57);
// fos.write(55);
//public void write(byte[] b):寫一個字節(jié)數(shù)組
byte[] bys={97,98,99,100,101};
fos.write(bys);
//public void write(byte[] b,int off,int len):寫一個字節(jié)數(shù)組的一部分
fos.write(bys,1,3);
//釋放資源
fos.close();
}
}
字節(jié)流寫數(shù)據(jù)加入異常處理
public class FileOutputStreamDemo4 {
public static void main(String[] args) {
// 分開做異常處理
// FileOutputStream fos = null;
// try {
// fos = new FileOutputStream("fos4.txt");
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
//
// try {
// fos.write("java".getBytes());
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// try {
// fos.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// 一起做異常處理
// try {
// FileOutputStream fos = new FileOutputStream("fos4.txt");
// fos.write("java".getBytes());
// fos.close();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// 改進版
// 為了在finally里面能夠看到該對象就必須定義到外面羹幸,為了訪問不出問題脊髓,還必須給初始化值
FileOutputStream fos = null;
try {
// fos = new FileOutputStream("z:\\fos4.txt");
fos = new FileOutputStream("fos4.txt");
fos.write("java".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 如果fos不是null,才需要close()
if (fos != null) {
// 為了保證close()一定會執(zhí)行栅受,就放到這里了
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.字節(jié)流讀取數(shù)據(jù)
/*
* 字節(jié)輸入流操作步驟:
* A:創(chuàng)建字節(jié)輸入流對象
* B:調用read()方法讀取數(shù)據(jù)将硝,并把數(shù)據(jù)顯示在控制臺
* C:釋放資源
*
* 讀取數(shù)據(jù)的方式:
* A:int read():一次讀取一個字節(jié)
* B:int read(byte[] b):一次讀取一個字節(jié)數(shù)組
* C:int read(byte[] b):一次讀取一個字節(jié)數(shù)組
* 返回值其實是實際讀取的字節(jié)個數(shù)。
*/
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
// FileInputStream(String name)
// FileInputStream fis = new FileInputStream("fis.txt");
FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
// // 調用read()方法讀取數(shù)據(jù)屏镊,并把數(shù)據(jù)顯示在控制臺
// // 第一次讀取
// int by = fis.read();
// System.out.println(by);
// System.out.println((char) by);
//
// // 第二次讀取
// by = fis.read();
// System.out.println(by);
// System.out.println((char) by);
//
// // 第三次讀取
// by = fis.read();
// System.out.println(by);
// System.out.println((char) by);
// // 我們發(fā)現(xiàn)代碼的重復度很高依疼,所以我們要用循環(huán)改進
// // 而用循環(huán),最麻煩的事情是如何控制循環(huán)判斷條件呢?
// // 第四次讀取
// by = fis.read();
// System.out.println(by);
// // 第五次讀取
// by = fis.read();
// System.out.println(by);
// //通過測試而芥,我們知道如果你讀取的數(shù)據(jù)是-1律罢,就說明已經讀取到文件的末尾了
// 用循環(huán)改進
// int by = fis.read();
// while (by != -1) {
// System.out.print((char) by);
// by = fis.read();
// }
// 最終版代碼
int by = 0;
// 讀取,賦值棍丐,判斷
while ((by = fis.read()) != -1) {
System.out.print((char) by);
}
// 數(shù)組的長度一般是1024或者1024的整數(shù)倍
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
// 釋放資源
fis.close();
}
}
字節(jié)流復制數(shù)據(jù)練習
/*
* 需求:把c盤下的a.txt的內容復制到d盤下的b.txt中
*
* 數(shù)據(jù)源:
* c:\\a.txt -- 讀取數(shù)據(jù)-- FileInputStream
* 目的地:
* d:\\b.txt -- 寫出數(shù)據(jù) -- FileOutputStream
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
// 封裝數(shù)據(jù)源
FileInputStream fis = new FileInputStream("c:\\a.txt");
// 封裝目的地
FileOutputStream fos = new FileOutputStream("d:\\b.txt");
// 復制數(shù)據(jù)
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 釋放資源
fos.close();
fis.close();
}
}
3.字節(jié)緩沖流
字節(jié)流一次讀寫一個數(shù)組的速度明顯比一次讀寫一個字節(jié)的速度快很多误辑,這是加入了數(shù)組這樣的緩沖區(qū)效果,java本身在設計的時候歌逢,也考慮到了這樣的設計思想(裝飾設計模式后面講解)巾钉,所以提供了字節(jié)緩沖區(qū)流。
字節(jié)緩沖輸出流:BufferedOutputStream秘案,字節(jié)緩沖輸入流:BufferedInputStream砰苍。
/*
* 通過定義數(shù)組的方式確實比以前一次讀取一個字節(jié)的方式快很多,所以阱高,看來有一個緩沖區(qū)還是非常好的赚导。
* 既然是這樣的話,那么赤惊,java開始在設計的時候吼旧,它也考慮到了這個問題,就專門提供了帶緩沖區(qū)的字節(jié)類荐捻。
* 這種類被稱為:緩沖區(qū)類(高效類)
* 寫數(shù)據(jù):BufferedOutputStream
* 讀數(shù)據(jù):BufferedInputStream
*
* 構造方法可以指定緩沖區(qū)的大小黍少,但是我們一般用不上,因為默認緩沖區(qū)大小就足夠了处面。
*
* 為什么不傳遞一個具體的文件或者文件路徑厂置,而是傳遞一個OutputStream對象呢?
* 原因很簡單,字節(jié)緩沖區(qū)流僅僅提供緩沖區(qū)魂角,為高效而設計的昵济。但是呢,真正的讀寫操作還得靠基本的流對象實現(xiàn)。
*/
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// BufferedOutputStream(OutputStream out)
// FileOutputStream fos = new FileOutputStream("bos.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
// 簡單寫法
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("bos.txt"));
// 寫數(shù)據(jù)
bos.write("hello".getBytes());
// 釋放資源
bos.close();
}
}
字節(jié)緩沖流復制數(shù)據(jù)練習
/*
* 需求:把e:\\a.mp4復制到當前項目目錄下的b.mp4中
*
* 字節(jié)流四種方式復制文件:
* 基本字節(jié)流一次讀寫一個字節(jié): 共耗時:117235毫秒
* 基本字節(jié)流一次讀寫一個字節(jié)數(shù)組: 共耗時:156毫秒
* 高效字節(jié)流一次讀寫一個字節(jié): 共耗時:1141毫秒
* 高效字節(jié)流一次讀寫一個字節(jié)數(shù)組: 共耗時:47毫秒
*/
public class CopyMp4Demo {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
// method1("e:\\a.mp4", "copy1.mp4");
// method2("e:\\a.mp4", "copy2.mp4");
// method3("e:\\a.mp4", "copy3.mp4");
method4("e:\\a.mp4", "copy4.mp4");
long end = System.currentTimeMillis();
System.out.println("共耗時:" + (end - start) + "毫秒");
}
// 高效字節(jié)流一次讀寫一個字節(jié)數(shù)組:
public static void method4(String srcString, String destString)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
// 高效字節(jié)流一次讀寫一個字節(jié):
public static void method3(String srcString, String destString)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));
int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);
}
bos.close();
bis.close();
}
// 基本字節(jié)流一次讀寫一個字節(jié)數(shù)組
public static void method2(String srcString, String destString)
throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fos.close();
fis.close();
}
// 基本字節(jié)流一次讀寫一個字節(jié)
public static void method1(String srcString, String destString)
throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
}
}