總結:
File 類 僅能獲取文件的屬性數據或者是修改文件的屬性數據而已,不能讀取文件內容數據。
如果需要操作文件內容數據,那麼就需要學習”IO流”技術
IO流類別:
1. 流向劃分
輸入流
輸出流
什麼時候使用輸入流什麼時候使用輸出流?
以當前程序作爲參照物,數據流入 則使用輸入流, 數據流出則使用輸出流。
- 處理單位:
字節流:字節流就是用於讀取文件的字節數據的,讀取到的數據不會經過任何的處理。
字符流: 讀取到的字節數據還會幫你轉換成你看得懂的字符數據,讀取的是以字符作單位 的數據。 字符流 = 字節流+ 解碼
1字節流
1.1 InputStream
輸入字節流:
———|InputStream 抽象類 輸入字節流的基類。
————| FileInputStream 讀取文件數據 的輸入字節流
使用FileInputStream 讀取文件數據步驟:
找到目標文件
建立數據的輸入通道
- 讀取文件數據
1.1.1 常用的讀取文件數據方式:使用循環配合緩衝 數組讀取 能讀取完一個文件數據,速度快
public static void read() throws IOException{
//找到目標文件
File file = new File("F:\\a.txt");
//建立數據的通道
FileInputStream fileInputStream= new FileInputStream(file);
//讀取數據
byte[] buf = new byte[1024]; //緩衝字節數組的長度一般都是1024的倍數。 緩衝字節數組一般越大效率越高
int length = 0 ; //記錄本次讀取的自己個數。
while((length = fileInputStream.read(buf))!=-1){
System.out.print(new String(buf,0,length));
}
//關閉資源(釋放資源文件)
fileInputStream.close();
}
1.2 OutputStream
輸出字節流:
——–| OutputStream 抽象類,所有輸出字節字節流的父類。
————| FileOutputStream 向文件輸出數據的輸出字節流。
使用FileOutputStream步驟:
1. 找到目標文件
2. 建立數據的輸出通道
3. 準備數據,把數據寫出
4. 把字符串轉成字節數組
5. 字節數組寫出
6. 關閉資源
FileOutputStream要注意的細節:
1. new FileOutputStream 的時候,如果目標文件不存在,那麼會先創建目標 文件,然後再寫入。
2. new FileOutputStream(file) 如果目標文件已經存在,那麼會先清空 目標文件的數據,然後再寫入新的數據.
3. 寫入數據的時候如果需要以追加的形式寫入,那麼需要使用new FileOutputStream(file,true) 這個構造函數。
4. 使用write(int b)方法的時候,雖然參數接受的一個int類型的數據,但是實際上只會把數據的低八位寫出,其他24位丟棄。
00000000-00000000-00000001-10000000
write(byte[] b, int off, int len)
1.2.1常用寫出的三種方式
//方式一: 先把數據轉成字節數組然後再寫出。
public static void write1() throws IOException{
//找到目標文件
File file = new File("F:\\a.txt");
//建立數據的輸出通道
FileOutputStream fileOutputStream = new FileOutputStream(file,true); //第二個參數爲true時,寫入文件數據就是以追加的形式寫入的
//準備數據, 把數據寫出
String str = "\r\nhello world";
//把字符串轉成字節數組
byte[] buf = str.getBytes();
//把字節數組寫出
fileOutputStream.write(buf);
//關閉資源
fileOutputStream.close();
}
//方式二
public static void write2() throws IOException {
// 找到目標文件
File file = new File("F:\\a.txt");
// 建立數據的輸出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
String data = "abcd";
byte[] buf = data.getBytes(); // 97 98 99 100
fileOutputStream.write(buf, 0, 2); // 指定開始的索引值與字節個數寫出。
fileOutputStream.close();
}
//方式三: 每次只能寫 一個字節的數據 。
public static void write3() throws IOException{
//找到目標文件
File file = new File("f:\\a.txt");
//建立數據的輸出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
//把數據寫出
fileOutputStream.write('h');
fileOutputStream.write('e');
fileOutputStream.write('l');
fileOutputStream.write('l');
fileOutputStream.write('o');
//關閉資源
fileOutputStream.close();
}
/*
4. 使用write(int b)方法的時候,雖然參數接受的一個int類型的數據,但是實際上只會把數據的低八位寫出,其他24位丟棄。
00000000-00000000-00000001-10000000
*/
public static void writeTest() throws FileNotFoundException, IOException {
File file = new File("F:\\b.txt");
//建立數據輸出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
//把數據寫出
fileOutputStream.write(384);
//關閉資源
fileOutputStream.close();
}
1.3 字節流文件拷貝
File inFile = new File("F:\\美女\\1.mp3");
File outFile = new File("E:\\拷貝.mp3");
//建立數據通道
FileInputStream fileInputStream = new FileInputStream(inFile);
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
//建立緩衝字節數組,邊讀邊寫
byte[] buf = new byte[1024];
int length = 0 ; //用於記錄每次讀取的字節個數
while((length=fileInputStream.read(buf))!=-1){ // 700 300
fileOutputStream.write(buf,0,length);
}
//關閉資源(關閉資源的原則:先開後關,後開先關)
fileOutputStream.close();
fileInputStream.close();
1.4 字節流的異常處理
//拷貝圖片
public static void copyImage(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try{
//找到目標文件
File inFile = new File("F:\\美女\\1.jpg");
File outFile = new File("F:\\拷貝.jpg");
//建立數據的輸入輸出通道
fileInputStream = new FileInputStream(inFile);
fileOutputStream = new FileOutputStream(outFile);
//建立緩衝字節數組,邊讀邊寫
byte[] buf = new byte[1024];
int length = 0 ;
while((length = fileInputStream.read(buf))!=-1){
fileOutputStream.write(buf,0,length);
}
}catch(IOException e){
System.out.println("拷貝出錯了...");
throw new RuntimeException(e);
//關閉資源的原則: 先開後關, 後開先關。
}finally{
try{
if(fileOutputStream!=null){
//關閉資源
fileOutputStream.close();
}
}catch(IOException e){
throw new RuntimeException(e);
}finally{
try{
if(fileInputStream!=null){
fileInputStream.close();
}
}catch(IOException e){
throw new RuntimeException(e);
}
}
}
}
1.5 字節緩衝流
使用FileInputStream讀取文件數據的時候如何讀取效率是最高?
使用字節數組作爲緩衝區讀取的效率是最高的。
1.5.1 輸入字節緩衝流
我們知道使用緩衝字節數組讀取文件的效率最高,sun也知道使用緩衝字節數組讀取的效率高,這時候sun爲了方便我們工作,編寫一個緩衝輸入字節流給我去使用。
緩衝輸入字節流的作用: 提高我們讀取文件數據的效率。
輸入字節流的體系:
———-| InputStream 抽象類 所有輸入字節流的基類
————–| FileInputStream 讀取文件數據的輸入字節流
————–|BufferedInputStream 緩衝輸入字節流 該類的本質其實只是在內部維護了一個8kb的字節數組而已。 主要是爲了提高我們的讀取文件 的效率。
凡是緩衝流都沒有讀寫文件的能力。
BuffereInputStream注意的事項:
1. BuffereInputStream 的close方法實際上關閉的就是你傳遞進去的FileInputStream對象。
public static void readTest() throws IOException {
//第一步:找到目標文件
File file = new File("F:\\a.txt");
//第二步:建立文件與程序的輸入通道
FileInputStream fileInputStream = new FileInputStream(file);
//第三部:建立緩衝輸入字節流
/*
疑問: 爲什麼創建BufferedInputStream對象需要傳入一個InputStream的對象呢?
BufferedInputStream沒有讀取文件 數據的能力,但是又要讀取文件的數據,這時候只能依賴一個具備
讀取文件數據能力的對象。
*/
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
//讀取文件數據
int content = 0;
/*
疑問: BufferedInputStream 的read方法每次只是讀取一個字節的數據,FileInputStream的read方法每次也是讀取一個字節的數據
那麼爲什麼說BufferedInputStream提高了讀取的效率呢?
InputStream流是指將字節序列從外設或外存傳遞到應用程序的流
BufferedInputStream流是指讀取數據時,數據首先保存進入緩衝區,其後的操作直接在緩衝區中完成。
*/
while((content = bufferedInputStream.read())!=-1){
System.out.print((char)content);
}
//關閉資源 實際上關的是inputStream 的close方法
bufferedInputStream.close();
} 這裏寫代碼片
1.5.2 輸出字節緩衝流
緩衝輸出字節流: 爲了提高寫文件的效率。
———| OutputStream 抽象類, 所有輸出字節流的基類。
————-| FileOutputStream 向文件寫出數據的輸出字節流對象。
————-| BufferedOutputStream 緩衝輸出字節流, 爲了提高寫文件數據的效率。
BufferedOutputStream 需要注意的事項: BufferedInputStream
1. 使用BufferedOutputStream的write方法時候,數據其實是寫入了BufferedOutputStream內部維護的字節數組中,只有你調用BufferedOutputStream的close方法或者是flush方法數據纔會真正的寫到硬盤上去或者內部維護的字節數組已經存儲滿數據了,這時候 數據纔會寫到硬盤上去。
2/. BufferedOutputStream 的close方法實際上關閉的就是你傳入的OutputStream對象的close方法。
//找到目標文件對象
File file = new File("f:\\a.txt");
//建立數據的輸出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
//建立緩衝輸出字節流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//寫數據
String data = "hello world";
bufferedOutputStream.write(data.getBytes());
// bufferedOutputStream.flush(); //把緩衝字節數組的數據寫到硬盤上去。
bufferedOutputStream.close();
1.5.3 使用緩衝輸入輸出字節流拷貝數據
public class CopyImage {
public static void main(String[] args) throws IOException {
long startTime = System.currentTimeMillis();
//找到目標文件
File inFile = new File("F:\\美女\\1.jpg");
File outFile = new File("E:\\拷貝.jpg");
//建立數據的輸入輸出通道
FileInputStream fileInputStream = new FileInputStream(inFile);
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
//建立緩衝輸入輸出字節流
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//邊讀邊寫
int content = 0 ;
while((content = bufferedInputStream.read())!=-1){
bufferedOutputStream.write(content);
// bufferedOutputStream.flush();
}
//關閉資源
bufferedOutputStream.close();
bufferedInputStream.close();
long endTime = System.currentTimeMillis();
System.out.println(endTime-startTime);
}
2 字符流
2.1 Reader
輸入字符流:
———-| Reader 抽象類 所有輸入字符流的基類。
—————-| FileReader 讀取文件數據的輸入字符流。
FileReader的 使用步驟:
1. 找到目標文件。
讀文件的兩種方式
//方式二:使用緩衝字符數組讀取文件的數據 推薦
public static void readTest2() throws IOException{
//找到目標文件
File file = new File("F:\\Demo1.java");
//建立數據的輸入通道
FileReader fileReader = new FileReader(file);
//建立緩衝字符數組,讀取文件的數據
char[] buf = new char[1024];
int length = 0;
while((length = fileReader.read(buf))!=-1){ // read(char[] buf) 讀取到的字符數組存儲到了字符數組中,返回了本次讀取到的字符個數。
System.out.print(new String(buf,0,length));
}
//關閉資源
fileReader.close();
}
//方式一:每次只會讀取一個字符的數據
public static void readTest() throws IOException{
//找到目標對象
File file = new File("f:\\a.txt");
//建立數據的輸入通道
FileReader fileReader = new FileReader(file);
//讀取文件數據
int content= 0;
while((content=fileReader.read())!=-1){ // FileReader的read()方法每次讀取一個字符的數據,如果讀到 了文件末尾返回-1表示。
System.out.print((char)content);
}
//關閉資源
fileReader.close();
}
2.2 writer
輸出字符流 :
——–| Writer 抽象類 輸出字符流的基類。
————| FileWriter 向文件寫出數據輸出字符流.
FileWriter 使用步驟: FileReader
1. 找到目標文件
2. 建立數據的輸出通道
3. 寫出數據
4. 關閉資源
FileWriter 要注意的事項:
1. new FileWriter(file)的時候 , 如果目標文件不存在,那麼會創建目標文件對象, 如果目標文件已經存在了,那麼則不再重新創建。
2. 使用new FileWriter(file) 這個構造方法的時候,默認是會先清空文本的數據,然後再寫入新的數據。如果需要追加數據則需要使用 new FileWriter(file,true)這個構造方法。
3. 使用FileWriter的write方法的時候,數據是寫入了FileWriter內部維護的字符數組中,如果需要把數據真正的寫到硬盤上去,需要調用flush方法或者 是close方法或者是內部維護的字符數組已經滿了,這時候也會寫到硬盤上。
public static void writerTest() throws IOException{
//找到目標文件
File file = new File("F:\\a.txt");
//建立數據 的輸出通道
FileWriter fileWriter = new FileWriter(file); //第二個參數爲true的意義是指追加數據。
//準備數據,把數據寫出
String data = "現在雨停了";
fileWriter.write(data);
//刷新輸出字符流
fileWriter.flush();
}
2.3 輸入輸出字符流的拷貝數據
總結 :
需求:使用輸入輸出字符流拷貝java文件.
何時使用字符流:何時使用字節流:
- 如果操作的是文本數據時,這時候就應該使用字符流。
- 如果操作的是非文本數據時,這時候則應該使用字節流。 圖片 、 視頻 、 音頻、 word
public class CopyJava {
public static void main(String[] args) throws IOException {
//找到目標文件
File inFile = new File("F:\\Demo1.java");
File outFile = new File("E:\\Demo2.java");
//建立數據 的輸入輸出通道
FileReader fileReader = new FileReader(inFile);
FileWriter fileWriter = new FileWriter(outFile);
//邊寫邊讀
char[] buf = new char[1024];
int length = 0 ;
while((length= fileReader.read(buf))!=-1){
fileWriter.write(buf,0,length);
}
//關閉資源
fileWriter.close();
fileReader.close();
}
}