菜鳥之路Day15一一IO流(一)
作者:blue
時間:2025.2.8
文章目錄
- 菜鳥之路Day15一一IO流(一)
- 0.概述
- 1.初識IO流
- 1.1.什么是IO流?
- 1.2.IO流的作用
- 1.3.IO流的分類
- 2.IO流的體系結構
- 3.字節輸出流的基本用法
- 4.字節輸入流的基本用法
- 5.異常處理(了解即可)
- 6.字符集
- 7.字符輸入流
- 7.1FileReader
- 7.2FileWriter
- 8.IO流綜合練習
- 8.1練習一
- 8.2練習二
- 8.3練習三
0.概述
文章內容,學習自黑馬程序員BV1yW4y1Y7Ms
1.初識IO流
1.1.什么是IO流?
答:存儲和讀取數據的解決方案
1.2.IO流的作用
答:用于讀寫數據(本地文件,網絡)
1.3.IO流的分類
按流的方向分
按操作文件的類型分
2.IO流的體系結構
3.字節輸出流的基本用法
FileOutputStream :操作本地文件的字節輸出流,可以把程序中的數據寫到本地文件中
書寫步驟:
①創建字節輸出流對象
? 細節1:參數是字符串表示的路徑或者File對象都是可以的
? 細節2:如果文件不存在會創建一個新的文件,但是要保證父級路徑是存在的
? 細節3:如果文件已經存在,則會清空文件
②寫數據
? 細節:write方法的參數是整數,但是實際上寫到本地文件中的是整數在ASCII上對應的字符
③釋放資源
? 細節:每次使用完流之后都要釋放資源
package IOStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamDemo1 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("src\\IOStream\\a.txt");//①創建字節輸出流對象fos.write(97);//②寫數據fos.close();//③釋放資源}
}
寫出數據的三種方式
public class FileOutputStreamDemo2 {public static void main(String[] args) throws IOException {/** void write(int b) 一次寫一個字節數據* void write(byte[] b) 一次寫一個字節數組數據** void write(byte[] b,int off,int len) 一次寫一個字節數組的部分數據* 參數一:數組* 參數二:起始索引 0* 參數三:個數 3* */FileOutputStream fos = new FileOutputStream("src\\IOStream\\a.txt");byte[] b = {97,98,99,100,101};fos.write(b,1,2);}
}
換行和續寫
public class FileOutputStreamDemo3 {public static void main(String[] args) throws IOException {/** 換行符:* windows:\r\n* Linux:\n* Mac:\r* 續寫:* 打開續寫開關即可,即創建對象的第二個參數* 默認是false表示關閉,創建對象會清空文件* 傳遞true,表示打開續寫,此時創建對象不會清空文件* */FileOutputStream fos = new FileOutputStream("src\\IOStream\\a.txt",true);String str1 = "kcbdkdvkdkjxkjdkj";String str2 = "\r\n";String str3 = "666";byte[] b1 = str1.getBytes();byte[] b2 = str2.getBytes();byte[] b3 = str3.getBytes();fos.write(b1);fos.write(b2);fos.write(b3);}
}
4.字節輸入流的基本用法
FileInputStream:操作本地文件的字節輸入流,可以把本地文件中的數據讀取到程序中來
書寫步驟:
①創建字節輸入流對象
? 細節1:如果文件不存在,就直接報錯
②讀數據
? 細節1:一次讀一個字節,讀出來的數據在ASCII上對應的數字
? 細節2:讀到文件末尾了,read方法返回-1
③釋放資源
? 細節:每次使用完流之后都要釋放資源
public class FileInputStreamDemo1 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("src\\IOStream\\a.txt");int ans = fis.read();while(ans!=-1){System.out.print((char)ans);ans = fis.read();}fis.close();//釋放資源}
}
文件拷貝的基本代碼
思想:邊讀邊寫
public class FileInputStreamDemo2 {public static void main(String[] args) throws IOException {//1.創建對象FileInputStream fis = new FileInputStream("C:\\Users\\zhangtenlan\\Desktop\\abc.txt");FileOutputStream fos = new FileOutputStream("src\\IOStream\\ans.txt");//2.拷貝//核心思想:邊讀邊寫int b;while((b=fis.read())!=-1){fos.write(b);}//3.釋放資源//規則:先開的最后關閉fos.close();fis.close();}
}
以上方法在拷貝大文件的時候速度非常的慢,原因就在于,每次只能讀取一個字節的數據,我們可以用read方法的一個重載來一次性讀取多個數據。
public int read(byte[] buffer) //一次讀一個字節數組數據
//注意:一次讀一個字節數組的數據,每次讀取會盡可能把數組裝滿
//長度盡量設置為1024的整數倍,不要太大,像1024*1024*5
例子:
public class FileInputStreamDemo3 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("src\\IOStream\\ans.txt");byte[] b = new byte[2];int len;while((len=fis.read(b))!=-1){ //當讀到的長度為-1時代表讀完了System.out.print(new String(b,0,len));}fis.close();}
}
拷貝大文件的寫法
public class FileInputStreamDemocratic {public static void main(String[] args) throws IOException {long start = System.currentTimeMillis();//記錄開始時間//1.創建對象FileInputStream fis = new FileInputStream("大文件");FileOutputStream fos = new FileOutputStream("目標位置");//2.拷貝int len;byte[] bytes = new byte[1024*1024*5];while((len=fis.read(bytes))!=-1){fos.write(bytes,0,len);}//3.釋放資源fos.close();fis.close();long end = System.currentTimeMillis();//記錄結束時間System.out.println(end-start);//看看程序運行花了多少時間}
}
5.異常處理(了解即可)
try{}catch(IOException e){}finally{//finally中代碼一定執行,除非JVM退出//所以釋放資源的代碼寫到這里再合適不過
}
6.字符集
1.在計算機中,任意數據都是以二進制的形式來存儲的
2.計算機中最小的存儲單元是一個字節
3.ASCII字符集中,一個英文占一個字節
4.簡體中文版Windows,默認使用GBK字符集
5.GBK字符集完全兼容ASCII字符集
? 注意:一個英文占一個字節,二進制第一位是0
? 一個中文占兩個字節,二進制高位字節的第一位是1
6.Unicode字符集的UTF-8編碼格式
? 注意:一個英文占一個字節,二進制第一位是0,轉成十進制是正數
? 一個中文占三個字節,二進制第一位是1,第一個字節轉成十進制是負數
為什么會有亂碼?
原因1:讀取數據時未讀完整個漢字
原因2:編碼和解碼時的方式不統一
Java中的解碼和編碼:
public class FileInputStreamDemo5 {public static void main(String[] args) throws UnsupportedEncodingException {/** java中的編碼方法* public byte[] getBytes() 使用默認方式進行編碼UTF-8* public byte[] getBytes(String charsetName) 使用指定方式進行編碼** java中的解碼方法* String(byte[] bytes) 使用默認方式進行解碼UTF-8* String(byte[] bytes,String charsetName) 使用指定方式進行解碼* */String str = "你好";byte[] res1 = str.getBytes();System.out.println(Arrays.toString(res1));System.out.println("=========================================================================");byte[] res2 = str.getBytes("GBK");System.out.println(Arrays.toString(res2));System.out.println("=========================================================================");String ans1 = new String(res1);System.out.println(ans1);System.out.println("=========================================================================");String ans2 = new String(res2,"GBK");System.out.println(ans2);}
}
7.字符輸入流
字符流
? 字符流 = 字節流+字符集
特點
? 輸入流:一次讀一個字節,遇到中文時,一次讀多個字節(所以適合處理中文)
? 輸出流:底層會把數據按照指定的編碼方式進行編碼,變成字節再寫到文件中
使用場景
? 對于純文本文件進行讀寫操作
書寫步驟
? ①創建字符輸入流對象
? ②讀取數據
? 注意:細節1:按字節進行讀取,遇到中文,一次讀多個字節,讀取后解碼,返回一個整數
? 細節2:讀到文件末尾了,read方法返回-1
? ③釋放資源
7.1FileReader
public class IOTestOne {public static void main(String[] args) throws IOException {/** 第一步:創建對象* public FileReader(File file) 創建字符輸入流關聯本地文件* public FileReader(String pathname)** 第二步:讀取數據* public int read() 讀取數據,讀到末尾返回-1* public int read(char[] buffer) 讀取多個數據,讀到末尾返回-1** 第三步:釋放資源* public void close 釋放資源* */FileReader fr = new FileReader("src\\IOTest\\a.txt");int ch;while((ch=fr.read())!=-1){System.out.print((char)ch);}fr.close();}
}/*有參的readFileReader fr = new FileReader("src\\IOTest\\a.txt");char[] chars = new char[2];int len;while((len=fr.read(chars))!=-1){//有參read返回值是System.out.print(new String(chars,0,len));}r.close();
*/
7.2FileWriter
①創建字符輸出流對象
? 細節1:參數是字符串表示的路徑或者是File對象都可以
? 細節2:如果文件不存在會創建一個新的文件,但是要保證父級路徑是存在的
? 細節3:如果文件已經存在,則會清空文件,如果不想清空可以打開續寫開關
②寫數據
? 細節:如果write方法的參數是整數,但是實際上寫到本地文件中的是整數在字符集上對應的字符
③釋放資源
? 細節:每次使用完流之后都要釋放資源
public class IOTestTwo {public static void main(String[] args) {/** 第一步:創建對象* public FileWriter(File file)* public FileWriter(String pathname)* public FileWriter(File file,boolean append) 續寫開關* public FileWriter(String pathname,boolean append)** 第二步:讀取數據* void write(int c)* void write(String str)* void write(String str,int off,int len)* void write(char[] cbuf)* void write(char[] cbuf,int off,int len)** 第三步:釋放資源* public void close() * */}
}
8.IO流綜合練習
字節流和字符流的使用場景
? 字節流:拷貝任意類型的文件
? 字符流:讀取純文本文件中的數據,往純文本文件中寫出數據
8.1練習一
拷貝文件夾,考慮子文件夾
public class Test1 {public static void main(String[] args) throws IOException {File src = new File("C:\\Users\\zhangtenlan\\Desktop\\src");//數據源File dest = new File("C:\\Users\\zhangtenlan\\Desktop\\dest");//目的地copydir(src,dest);}private static void copydir(File src, File dest) throws IOException {dest.mkdirs();//1.進入數據源File[] arr = src.listFiles();//2.遍歷數據源for(File file:arr){//3.如果是文件,則拷貝if(file.isFile()) {FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));byte[] bytes = new byte[1024];int len;//邊讀邊寫while((len= fis.read(bytes))!=-1){fos.write(bytes,0,len);}fos.close();fis.close();}//4.如果是文件夾,則遞歸else {copydir(file,new File(dest,file.getName()));}}}
}
8.2練習二
文件加密
為了保證文件的安全性,就需要對原始文件進行加密存儲,再使用的時候再對其進行解密處理。
加密原理:
? 對原始文件中的每一個字節數據進行更改,然后將更改以后的數據存儲到新文件中
解密原理:
? 讀取加密之后的文件,按照加密規則反向操作,變成原始文件
//完成這個功能,我們可以利用異或的原理
//加密,我們可以令每個字節都異或上一個數字
public class Test2 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("src\\yuan.png");FileOutputStream fos = new FileOutputStream("src\\jiami");int b;while((b=fis.read())!=-1){fos.write(b^5);}fos.close();fis.close();}
}
//解密,我們取原來加密過的圖片,再次異或上這個數字
public class Test2 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("src\\jiami");FileOutputStream fos = new FileOutputStream("src\\jiemi.png");int b;while((b=fis.read())!=-1){fos.write(b^5);}fos.close();fis.close();}
}
8.3練習三
文本文件中有以下數據:2-1-9-4-7-8
將文本中的數據進行排序,變成以下數據:1-2-4-7-8-9
public class Test3 {public static void main(String[] args) throws IOException {//1.讀取數據//純文本文件,可以使用字符流來操作FileReader fr = new FileReader("src\\a.txt");StringBuilder sb = new StringBuilder();int b;while((b=fr.read())!=-1){sb.append((char)b);}fr.close();//2.排序ArrayList<Integer> list = new ArrayList<>();String[] arr = sb.toString().split("-");//分離-for (String s : arr) {//將數據轉為整數類型,為排序做準備list.add(Integer.parseInt(s));}Arrays.sort(arr);//排序//3.寫回FileWriter fw = new FileWriter("src\\b.txt");for (int i = 0; i < arr.length; i++) {if(i==arr.length-1) {fw.write(arr[i]+"");}else {fw.write(arr[i]+"-");}}fw.close();}
}