14、java——IO流
3、IO流
(1)前提需求: 讀寫檔案內部的內容,上傳,下載
(2)流: 管道 資料以先入先出的方式進行流動,資料來源--資料-->目的地
(3)io包: 一系列io相關類 File...
(4)流的分類:
①按照流向分:
輸入流,輸出流
(以大腦為中心,以程式為中心,明確資料來源和目的地,能夠確定輸入還是輸出)
②按照操作單元分;
位元組流 : 萬能流,任意內容都能轉為位元組,字元流 : 只能傳輸純文字的內容
③按照功能分:
節點流 : 真實做讀入寫出的流,功能流 : 增強節點流的功能,加強效能
分類之間是相輔相成的
(5)位元組流:
①位元組輸入流 InputStream
檔案位元組輸入流 FileInputStream
功能: 節點流 流向分:輸入流 操作單元:位元組流
功能: 讀入read() 關閉close
②位元組輸出流 OutputStream
public class Class001_IO {
public static void main(String[] args) throws IOException {
//FileInputStream(File file) 通過開啟與實際檔案的連線來建立 FileInputStream ,該檔案由檔案系統中的 File物件 file命名。
File src = new File("D://test2.txt"); //資料來源
//建立流
InputStream is = new FileInputStream(src);
//讀入資料 int read() 從此輸入流中讀取一個位元組的資料。 讀到檔案末尾返回-1
int num = is.read();
//處理資料
System.out.println((char)num);
System.out.println((char)(is.read()));
System.out.println((char)(is.read()));
System.out.println(is.read());
//關閉流
is.close();
}
}
③read() 從此輸入流中讀取一個位元組的資料。 讀到檔案末尾返回-1
每次讀取一個位元組,重複通過迴圈讀入,可以簡化程式碼結構
public class Class002_IO {
public static void main(String[] args) throws IOException {
//建立流
//FileInputStream (String name) 通過開啟與實際檔案的連線來建立 FileInputStream ,該檔案由檔案系統中的路徑名 name命名。
InputStream is = new FileInputStream("D://test2.txt");
//讀入資料
int num = -1;
while((num=is.read())!=-1){
//處理資料
System.out.println((char)num);
}
//關閉流
is.close();
}
}
④public byte[] readAllBytes() throws IOException
從輸入流中讀取所有剩餘位元組。 此方法將阻塞,直到讀取了所有剩餘位元組並檢測到流結束,或者丟擲異常。 此方法不會關閉輸入流。
當此流到達流的末尾時,此方法的進一步呼叫將返回空位元組陣列,請注意,此方法適用於方便將所有位元組讀入位元組陣列的簡單情況。 它不用於讀取包含大量資料的輸入流。起始版本: java9
public class Class004_IO {
public static void main(String[] args) throws IOException {
//1.構建流
InputStream is = new FileInputStream("D://test2.txt");
//2.讀入所有資料
byte[] arr = is.readAllBytes();
//3.處理資料
System.out.println(new String(arr));
//4.關閉
is.close();
}
}
(6)位元組輸出流
①OutputStream 此抽象類是表示輸出位元組流的所有類的超類。
②FileOutputStream : 檔案輸出流,將資料寫出到指定檔案中
③注意:如果目的地檔案不存在,系統會自動建立
輸出流如果目的地檔案存在,內容預設覆蓋,設定追加
(7)檔案拷貝,資料來源--> 讀入---> 程式 --> 寫出 --> 目的地
步驟:①建立流(輸入 輸出)②準備小汽車 位元組陣列③讀入-->寫出④刷出⑤關閉(後開啟的先關閉)
public class Class006_CopyFile {
public static void main(String[] args){
//1.建立流(輸入 輸出)
//作用域提升,為了能夠在finally中使用
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("D://test.txt");
os = new FileOutputStream("D://dest.txt");
//2.準備小汽車 位元組陣列
byte[] car = new byte[1024];
//3.讀入-->寫出
int len = -1; //記錄每次讀入到位元組陣列中資料的個數
while((len=is.read(car))!=-1){
//讀入多少位元組資料寫出多少位元組資料
os.write(car,0,len);
}
//4.刷出
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//5.關閉(後開啟的先關閉)
//預防空指標異常出現
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(8)字元輸入流 : 只能讀寫純文字資料
①輸入流 : Reader 字元輸入流的父類FileReader 檔案字元輸入流read(),read(char[]),close()
②輸出流 : Writer
public class Class001_IO {
public static void main(String[] args) throws IOException {
//1.建立流
//FileReader(String fileName)
//FileReader(File file)
Reader rd = new FileReader("D://test.txt");
//2.讀入
//char ch = (char)(rd.read());
//小汽車
char[] car = new char[1024];
//迴圈讀入
int len = -1;
while((len = rd.read(car))!=-1){
//3.處理資料
System.out.println(new String(car,0,len));
}
//4.關閉
rd.close();
}
}
③輸出流 : Writer 字元輸出流抽象父類,FileWriter 檔案字元輸出流write(),flush(),close()
public class Class002_IO {
public static void main(String[] args) throws IOException {
//1.建立流
/*
//FileWriter(File file)
//FileWriter(String fileName)
//FileWriter(File file, boolean append)
//FileWriter(String fileName, boolean append)
*/
Writer rt = new FileWriter("D://test.txt",true);
//2.準備資料
String msg = "今天也要加油鴨!!!";
//3.寫出
rt.write(msg);
//4.刷出
rt.flush();
//5.關閉
rt.close();
}
}
④字元流實現檔案拷貝,注意: 只能為純文字檔案
1、拷貝資料夾 :
(1)判斷要拷貝的檔案是檔案還是資料夾
是檔案: 呼叫工具類實現檔案拷貝
是資料夾: 建立資料夾,遍歷資料來源資料夾,獲取到所有的子檔案然後重複
public static void main(String[] args) {
copyDir("D://DDD","D://haha");
}
//拷貝資料夾
public static void copyDir(String src,String dest){
copyDir(src!=null?new File(src):null,dest!=null?new File(dest):null);
}
public static void copyDir(File src, File dest){
if(src==null || dest==null){
throw new NullPointerException();
}
if(!src.exists()){
System.out.println("資料來源不存在!!!");
return;
}
//拷問資料夾|檔案
copyDetail(src,dest);
}
//實現拷貝細節
public static void copyDetail(File src,File dest){
//拼接完整目的地路徑
dest = new File(dest,src.getName()); //D:\haha\hehe\DDD
//檔案
if(src.isFile()){
//如果目的地路徑不存在
if(!dest.getParentFile().exists()){
dest.getParentFile().mkdirs();
}
//檔案拷貝
CopyFileUtils.copyFile(src,dest);
}else if (src.isDirectory()){
//資料夾
//建立不存在的目的地路徑
dest.mkdirs();
//遍歷資料來源
File[] arr = src.listFiles();
for(File file:arr){ //D:\DDD\a.txt
copyDetail(file,dest); ////D:\haha\hehe\DDD
}
}
}
}
(2)按照功能分:
①節點流 : 真實做讀入寫出②功能流 : 加強效能③功能流都要包裹節點流使用
④緩衝流 : 功能流⑤作用: 提高讀寫效率
⑥位元組節點流:
FileInputStream 檔案流 | ByteArrayInputStream 位元組陣列流
FileOutputStream | ByteArrayOutputStream
⑤位元組緩衝流 : 位元組流功能流的一種
BufferedInputStream 位元組輸入緩衝流
BufferedOutputStream 位元組輸出緩衝流
⑥無新增功能,可以發生多型
⑦字元節點流
FileReader,FileWriter
⑧字元緩衝流
BufferedReader,BufferedWriter
存在新增方法: 不能發生多型
readLine(),newLine()
public class Class001_Buffered {
public static void main(String[] args) throws IOException {
//1.建立流
InputStream is = new BufferedInputStream(new FileInputStream("D://test.txt"));
OutputStream os = new BufferedOutputStream(new FileOutputStream("D://heihei.txt"));
//2.拷貝
byte[] car = new byte[1024];
int len = -1;
while((len=is.read(car))!=-1){
os.write(car,0,len);
}
//3.刷出
os.flush();
//4.關閉
os.close();
is.close();
}
}
2、基本資料型別流|Data流
(1)功能: 功能流 操作單元: 位元組流
(2)作用: 保留資料已經資料型別(基本資料型別+String)
DataInputStream,新增功能: readXxx()
DataOutputStream,新增功能: writeXxx()
(3)注意:①讀入與寫出的順序要保持一致②java.io.EOFException : 讀入的檔案不是原始檔
public class Class001_Data {
public static void main(String[] args) throws IOException {
readFromFile("D:/d.txt");
}
//讀入
public static void readFromFile(String path) throws IOException {
//1.建立流
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.讀入
int i = is.readInt();
boolean flag = is.readBoolean();
char ch = is.readChar();
String s = is.readUTF();
//3.處理資料
System.out.println(i);
System.out.println(flag);
System.out.println(ch);
System.out.println(s);
//4.關閉
is.close();
}
//寫出
public static void writeToFile(String path) throws IOException {
//1.建立輸出流
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.準備資料
int i = 1;
boolean flag = false;
char ch = 'c';
String str = "哈哈";
//3.寫出
out.writeInt(i);
out.writeBoolean(flag);
out.writeChar(ch);
out.writeUTF(str);
//4.刷出
out.flush();
//5.關閉
out.close();
}
}
3、Object 流| 物件流 | 引用資料型別流
(1)作用: 讀寫物件資料|引用資料型別的資料(包含基本資料型別)
ObjectInputStream 反序列化輸入流,新增功能: readObject()
ObjectOutputStream 序列化輸出流,新增功能: writeObject(Object obj)
(2)序列化: 將物件資料轉換一個可儲存或者可傳輸的狀態過程
(3)特性:
①先序列化後反序列化
②不能所有的型別都能序列化 java.io.Serializable
③不是所有的屬性都需要序列化
④靜態的內容不會序列化
⑤如果父類實現序列化,子類沒有實現,可以序列化所有的成員
⑥如果子類實現序列化,父類實現,只能序列化子類成員
(4)通過序列號控制版本不一致問題:
①實現Serializable介面的型別預設生成序列號,序列號會根據成員的修改做更新 serialVersionUID = -5204947308809070324
②控制版本的統一問題: 控制型別修改之前與之後序列不變
③通過工具生成序列號: a.實現Serializable介面 b.setting設定 c.選中類名->alt+enter->生成序列號
public class Class001_Object {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//writeToFile("D://e.txt");
readFile("D://e.txt");
}
//反序列化
public static void readFile(String path) throws IOException, ClassNotFoundException {
//1.輸入流
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.讀入
User obj1 = (User) in.readObject();
int[] arr = (int[]) in.readObject();
//3.處理資料
System.out.println(obj1);
System.out.println(Arrays.toString(arr));
//4.關閉
in.close();
}
//序列化輸出
public static void writeToFile(String path) throws IOException {
//1.輸出流
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.資料
User user = new User("zhangsan",18,"123");
int[] arr = {1,2,3,4};
//3.寫出
out.writeObject(user);
out.writeObject(arr);
//4.刷出
out.flush();
//5.關閉
out.close();
//修飾user物件的成員,靜態
user.username = "lisi";
user.password = "4321";
}
}
class User implements Serializable{
private static final long serialVersionUID = -5204947308809070324L;
public String username;
//transient 修飾的欄位不會序列化
public transient int age;
public static String password;
//成員的修改: 新增的成員
public int vip;
public int id; //使用者編號
public User() {
}
public User(String username, int age, String password) {
this.username = username;
this.age = age;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
", password='" + password + '\'' +
'}';
}
}
(1)CommonsIO 是apache的一個開源的工具包,封裝了IO操作的相關類,使用Commons IO可以很方便的讀寫檔案,url原始碼等。
(2)使用第三方元件的方式|步驟:
①下載原始碼資源,找到核心jar包
②專案下新建資料夾lib,放入jar包
③commons-IO 需要加入classpath 的第三方 jar 包內的 class 檔案才能在專案中使用,選中jar包右鍵->add as lib...
public class Class001_CommonsIO {
public static void main(String[] args) throws IOException {
//1.建立File物件
File src = new File("D://a.txt");
File dest = FileUtils.getFile("D://f.txt");
//FilenameUtils
//isExtension(String fileName, String text) // 判斷fileName是否是text字尾名
//FilenameUtils.getBaseName(String filename) // 去除目錄和字尾後的檔名 System.out.println(FilenameUtils.getBaseName("D://DDD/haha.txt"));; System.out.println(FilenameUtils.getName("D://DDD/haha.txt"));; System.out.println(FilenameUtils.isExtension("D://DDD/haha.txt","txt"));;
//FileUtils
//FileUtils.copyFile(File srcFile, File destFile)` // 複製檔案
FileUtils.copyFile(src,dest);
// **複製資料夾**
//FileUtils.copyDirectory(File srcDir, File destDir)` // 複製資料夾(資料夾裡面的檔案內容也會複製)
FileUtils.copyDirectory(new File("D://DDD"), new File("D://hehe/DDD"));
//FileUtils.copyDirectory(File srcDir, File destDir, FileFilter filter)` // 複製資料夾,帶有檔案過濾功能
FileUtils.copyDirectory(new File("D://DDD"), new File("D://houhou/DDD"), FileFilterUtils.fileFileFilter());
//**把字串寫入檔案**
//`FileUtils.writeStringToFile(File file, String data, String encoding)` // 字串以指定的編碼寫到檔案
//`FileUtils.writeStringToFile(File file, String data, String encoding, boolean append)`// 指定知否追加
FileUtils.writeStringToFile(src,"yyds!!!!","UTF-8",true);
}
}