java IO流 對檔案操作的程式碼集合

兩千個祕密發表於2019-02-22

Io流

按照分類 有兩種分類  

流向方向: 有輸入流和輸出流

按照操作型別有:位元組流和字元流

 

按照流向方向

位元組流的一些操作    
        //讀檔案
        FileInputStream fis = new FileInputStream("java.txt");
        int temp = fis.read()//一次讀取一個位元組
        System.out.println(temp); //列印的字母的碼值  讀取完返回-1
        System.out.println((char)temp);//列印字母
        
        
        byte[] arr = new byte[6]; //定義byte陣列告訴系統一次讀取幾個位元組,減少記憶體和硬碟之間的通訊,可以提高效率
        int temp = bis.read(arr); //有參的read方法返回的int值是讀取了幾個位元組
        System.out.println(new String(arr, 0, temp)); // 
        
        //寫檔案
        FileOutputStream fos = new FileOutputStream("file" + File.separator + "1024.txt",true);
            //如果該檔案不存在,則會自動建立
            //傳入true會在檔案內容的後面寫入文字,而不會覆蓋之前的內容
            //開發中檔案分隔符最好不要直接寫  而是寫 File.separator
            
        
        String msg = "Hello World";
        fos.write("
".getBytes());//換行,並向檔案寫入  String.getBytes() 因為要以位元組的形式傳入
        fos.write(msg.getBytes());
        
        
        String msg = "好好學習";
        //一個漢字佔2個位元組,向裡面一次傳入3個位元組會導致亂碼
        fos.write(msg.getBytes(), 0, 3);
        
        
        byte[] arr = new byte[6];//一次性寫這麼多位元組
        int temp = fis.read(arr);
        fos.write(arr, 0, temp);

        fos.flush();//重新整理
        
        
        //新的jdk7寫法是在try括號()裡面寫檔案的連結, 這樣最後就不用關閉了,會自動關閉
        
        //緩衝輸入流底層預設建立一個大小是8192長度的byte陣列
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("java.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("file" + File.separator + "good.txt"));
        
        int temp = bis.read();//temp依然為ascii瑪  每次一個
        

一些練習

利用BufferedInputStream 和 BufferedOutputStream 實現將一個檔案copy到另一個檔案

package com.wpbxx.stream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferFileCopy {

    public static void main(String[] args) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream("java.txt"));
            bos = new BufferedOutputStream(new FileOutputStream("file" + File.separator + "good.txt"));
            int temp;
            while((temp = bis.read()) != -1){
                bos.write(temp);
            }
            bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                bis.close();
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
        
    }

}

檔案的加密  將一個位元組異或一個數字實現 在傳輸時進行檔案的加密

package com.wpbxx.stream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CodeFile {

    public static void main(String[] args) {
        //jdk7新寫法
        try (
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream("圖片.png"));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code.png"));
                ) {
            
            int temp;
            while((temp = bis.read()) != -1){
                bos.write(temp ^ 88);
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

檔案解密

package com.wpbxx.stream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DecodeFile {

    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code.png"));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("decode.png"));) {
            int temp;
            while ((temp = bis.read()) != -1) {
                bos.write(temp ^ 88);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

字元流的一些操作  可以解決亂碼的問題

        ////注意:字元流不能讀取非文字檔案
        FileReader fr = new FileReader("java.txt");
        int temp;
        while ((temp = fr.read()) != -1) {
            System.out.println((char) temp); //一次一個字元
        }
        //使用緩衝字元流
        BufferedReader br = new BufferedReader(new FileReader("word.txt"));
        String msg;
        while((msg = br.readLine()) != null){  //一次可以讀取一行
            System.out.println(msg); 
        }
        //
        FileWriter fw = new FileWriter("word.txt");
        fw.write("我喜歡學習java");
        fw.write(97);
        
        BufferedWriter bw = new BufferedWriter(new FileWriter("newbuffered.txt"));
        bw.write("你好");
        bw.newLine();//回車換行
        bw.write("java");

 

 

同樣是copy檔案

package com.wpbxx.chario;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 使用緩衝流拷貝檔案
 * 注意:字元流不能讀取非文字檔案
 */
public class BufferFileCopy {

    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("java.txt"));
            BufferedWriter bw = new BufferedWriter(new FileWriter("file" + File.separator + "hellojava.txt"));    
                ) {
            String msg;
            while((msg = br.readLine()) != null){
                bw.write(msg);
                bw.newLine();
            }
            
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

}

 

 通過java中的File類實現對檔案的一些操作

        File file1 = new File("D:\hello.txt");
        //如果檔案存在,就不建立了,返回false,如果不存在就會建立,返回true
        System.out.println(file1.createNewFile());
        
        File file2 = new File("D:\new");
        //如果資料夾存在,就不建立了,返回false,如果不存在就會建立,返回true
        System.out.println(file2.mkdir());
        
        File file3 = new File("D:\wpbxx\1024");
        //可以建立多級目錄,如果資料夾存在,就不建立了,返回false,如果不存在就會建立,返回true
        System.out.println(file3.mkdirs());
        
        File file4 = new File("D:\wpbxx\1024.txt");
        //只能建立資料夾
        System.out.println(file4.mkdirs());
        
        File file5 = new File("1026.txt");
        //如果不寫碟符,會預設在專案的根目錄裡面建立
        System.out.println(file5.createNewFile());
        System.out.println(file5.exists());
        
        //舊名字
        File oldFile1 = new File("D:\world.txt");
        //新名字
        File newFile1 = new File("D:\wpbxx\java.txt");
        //如果兩個檔案路徑不一致,則會將舊檔案剪下到新的檔案路徑中再重新命名
        oldFile1.renameTo(newFile1);
        
        
        //不會將檔案放到回收站中,而是直接刪除
        File del = new File("D:\wpbxx\java.txt");
        
        File del1 = new File("D:\wpbxx");
        //如果資料夾下有其他檔案,則不會刪除
        System.out.println(del1.delete());
        
                File file2 = new File("D:\new.txt");
        //判斷是否是資料夾
        System.out.println(file2.isDirectory());
        //判斷是否是檔案
        System.out.println(file2.isFile());
        
        //判斷檔案是否存在
        System.out.println(file2.exists());
        
        File file3 = new File("D:\hidden");
        //判斷檔案是否隱藏
        System.out.println(file3.isHidden());
        
        
        File file1 = new File("1024.txt");
        //檢視絕對路徑
        System.out.println(file1.getAbsolutePath());
        //檔案的大小,單位是位元組
        System.out.println(file1.length());
        //最後修改時間
        Date date = new Date(file1.lastModified());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(sdf.format(date));
        
        File file2 = new File("F:\wpbxx\程式碼\code\chapter-08");
        //獲取目錄下的同級檔案或資料夾的名稱
        String[] nameArray = file2.list();
        for(String name : nameArray){
            System.out.println(name);
        }

幾個小練習

package com.wpbxx.exercise;

import java.io.File;
import java.util.Scanner;

/**
 * 問題:從鍵盤接收一個路徑,將這個路徑下的所有檔案和資料夾的名字按照層級列印。
 * 例如:
 *    wpbxx
 *              java
 *                  XXX.java
 *                  XXX.jpg
 *              php
 *                  XXX.php
 *              readme.txt
 * 
 * 分析:獲取路徑File物件中的File陣列
 *     遍歷陣列,取得File物件
 *     列印檔案或資料夾的名字
 *     如果是一個資料夾的話,使用遞迴重複上面的操作
 */
public class FileNames {
    
    //用來記錄縮排的次數
    private static int count = 0;

    public static void main(String[] args) {
        
        File file = getFile();
        
        getFileNames(file);
    }
    
    //每次呼叫該方法時,說明進入到一個新的資料夾的內部,需要增加一個縮排
    private static void getFileNames(File file) {
        //獲取路徑File物件中的File陣列
        File[] fileArray = file.listFiles();
        
        //遍歷陣列,取得File物件
        for(int i=0; i<fileArray.length; i++){
            
            //通過遍歷count來控制列印幾個縮排
            for(int j=0; j<count; j++){
                System.out.print("	");
            }
            
            //列印檔案或資料夾的名字
            System.out.println(fileArray[i]);
            
            
            
            //如果是一個資料夾的話,使用遞迴重複上面的操作
            if(fileArray[i].isDirectory()){
                count++;
                getFileNames(fileArray[i]);//陣列遍歷完最後一個File物件時,說明當前資料夾已經遍歷結束,需要做自減運算
                count--;
            }
            
        }
    }
    
    //獲取使用者輸入路徑的File物件
    private static File getFile() {
        
        System.out.println("請輸入一個資料夾路徑:");
        
        Scanner sc = new Scanner(System.in);
        //獲取使用者輸入的路徑,使用者輸入的路徑有可能是錯誤的,需要進行判斷
        while(true){
            String input = sc.nextLine();
            File file = new File(input);
            if(!file.exists()){
                System.out.println("您輸入的檔案路徑有誤,請重新輸入檔案路徑:");
            }else if(file.isFile()){
                //如果使用者輸入的路徑是一個檔案
                System.out.println("您輸入的路徑是一個檔案,請輸入一個資料夾的路徑");
            }else{
                return file;
            }
        }
    }
    
    

}
package com.wpbxx.exercise;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 問題:收費版軟體有試用次數,利用IO流的知識,模擬一個可以試用3次的功能,開啟3次之後提示使用者購買正版軟體
 * 
 * 分析:將試用的次數做加密處理後寫到txt檔案中
 *     使用IO流相關的知識將txt檔案中的內容讀取到記憶體中
 *     如果讀取的內容小於0時提示使用者購買正版軟體
 *     如果大於0小於等於3時,將試用次數做自減運算之後寫出到txt檔案中
 */
public class Trial {

    public static void main(String[] args) {
        //code();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream("src" + File.separator + "com"
                    + File.separator + "monkey1024" + File.separator + "exercise" + File.separator + "config.txt"));
            int temp = bis.read();
            //解密處理
            int count = temp ^ 66;
            if(count > 0 && count <= 3){
                count--;
                System.out.println("您的試用次數還剩餘" + count + "次");
                bos = new BufferedOutputStream(new FileOutputStream("src" + File.separator + "com"
                        + File.separator + "monkey1024" + File.separator + "exercise" + File.separator + "config.txt"));
                //做加密處理
                bos.write(count ^ 66);
                bos.flush();
            }else{
                System.out.println("您的試用次數已超出限制,請購買正版軟體!");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                //避免出現空指標
                if(bis != null){
                    bis.close();
                }
                if(bos != null){
                    bos.close();
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    //試用次數加密處理
    private static void code() {
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream("src" + File.separator + "com"
                    + File.separator + "monkey1024" + File.separator + "exercise" + File.separator + "config.txt"));
            //加密處理
            bos.write(3 ^ 66);
            bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                //避免出現空指標異常
                if(bos != null){
                    bos.close();
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
package com.wpbxx.exercise;

import java.io.File;

/**
 * 問題:統計專案根目錄下以.txt結尾的檔案數量,並將檔名列印出來
 * 分析:獲取專案根目錄下的檔名
 *     對檔名進行判斷是否是以.txt結尾
 */
public class FindTxt {

    public static void main(String[] args) {
        File file = new File("F:\wpbxx\01-JavaSE\程式碼\code\chapter-08");
        File[] fileArray = file.listFiles(); //返回一個File列表就是該目錄下的File列表
        
        //統計出現次數
        int count = 0;
        for(File name : fileArray){
            String s = name.toString();
            
            //判斷是否是以.txt檔案結尾
            if(s.endsWith(".txt")){
                if(name.isFile()){
                    count++;
                    System.out.println(name);
                }
            }
        }
        
        System.out.println("以.txt檔案結尾的數量是" + count + "個");
        
    }
}
package com.monkey1024.file;

import java.io.File;
import java.io.FilenameFilter;

/**
 * 問題:統計專案根目錄下以.txt結尾的檔案數量,並將檔名列印出來
 * 使用檔案過濾器實現上述需求
 */
public class FilenameFilterTest01 {

    public static void main(String[] args) {
        File file = new File("F:\monkey1024\01-JavaSE\程式碼\code\chapter-08");
        String[] nameArray = file.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name){
                //獲取根目錄下每個檔案的File物件
                File file1 = new File(dir, name);
                //編寫篩選條件
                return file1.isFile() && file1.getName().endsWith(".txt");
            }
        });
        
        System.out.println("以.txt結尾的檔案個數是" + nameArray.length + "個");
        
        for(String name : nameArray){
            System.out.println(name);
        }
    }

}
package com.wpbxx.file;

import java.io.File;
import java.io.FilenameFilter;

/**
 * 問題:統計專案根目錄下以.txt結尾的檔案數量,並將檔名列印出來
 * 使用檔案過濾器實現上述需求
 */
public class FilenameFilterTest01 {

    public static void main(String[] args) {
        File file = new File("F:\wpbxx\01-JavaSE\程式碼\code\chapter-08");
        String[] nameArray = file.list(new FilenameFilter() {//重寫accept方法  
            @Override
            public boolean accept(File dir, String name){//將過濾的規則寫進來
                //獲取根目錄下每個檔案的File物件
                File file1 = new File(dir, name);
                //編寫篩選條件
                return file1.isFile() && file1.getName().endsWith(".txt");
            }
        });
        
        System.out.println("以.txt結尾的檔案個數是" + nameArray.length + "個");
        
        for(String name : nameArray){
            System.out.println(name);
        }
    }

}

 

 對物件的讀取

為啥要對物件讀取?

平時我們在Java記憶體中的物件,是無 法進行IO操作或者網路通訊的,因為在進行IO操作或者網路通訊的時候,人家根本不知道記憶體中的物件是個什麼東西,因此必須將物件以某種方式表示出來,即 儲存物件中的狀態。一個Java物件的表示有各種各樣的方式,Java本身也提供給了使用者一種表示物件的方式,那就是序列化。換句話說,序列化只是表示對 象的一種方式而已。OK,有了序列化,那麼必然有反序列化,我們先看一下序列化、反序列化是什麼意思。

序列化:將一個物件轉換成一串二進位制表示的位元組陣列,通過儲存或轉移這些位元組資料來達到持久化的目的。

反序列化:將位元組陣列重新構造成物件。

 

 

序列化只需要實現java.io.Serializable介面就可以了。序列化的時候有一個serialVersionUID引數,Java序列化機制是通過在執行時判斷類的serialVersionUID來驗證版本一致性的。 在進行反序列化,Java虛擬機器會把傳過來的位元組流中的serialVersionUID和本地相應實體類的serialVersionUID進行比較, 如果相同就認為是一致的實體類,可以進行反序列化,否則Java虛擬機器會拒絕對這個實體類進行反序列化並丟擲異常。serialVersionUID有兩 種生成方式:

摘自:https://www.cnblogs.com/szlbm/p/5504166.html  這個也比較詳細

如果一個類的物件支援序列化和反序列化,需要實現Serializable,Serializable中沒有任何方法,只是相當於一個標記

有一個類

package com.monkey1024.serializable;

import java.io.Serializable;

/**
 * 如果一個類的物件支援序列化和反序列化,需要實現Serializable
 * Serializable中沒有任何方法
 */
public class Student implements Serializable{
    
    
    /**
     * 自動生成序列化版本號
     */
    private static final long serialVersionUID = -716323668524282676L;

    private String name;
    
    //新增屬性後,使用反序列化時會報出InvalidClassException
    //transient修飾的變數不會被序列化
    transient private int age;
    
    private boolean sex;
    
    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
}

然後我們對這個類進行序列化和反序列化

        Student zhangsan = new Student();
        zhangsan.setName("張三");
        zhangsan.setAge(20);
        //
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("zhangsan"));
        oos.writeObject(zhangsan);
        oos.flush();
        
        //
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("zhangsan"));
        Student s = (Student)ois.readObject();
        System.out.println(s.getName());
        System.out.println(s.getAge());

 

相關文章