Java 異常 文件操作 IO流


1. 程序的異常

嚴重問題:Error 不處理,問題嚴重,比如內存溢出

問題:Exception:

編譯器問題:不是運行期RuntimeException的異常,必須進行處理,不處理將不能通過編譯

運行期問題:RuntimeException 這種問題也不處理,程序的嚴謹性問題

 如果程序出現了問題,我們沒有處理,虛擬機將默認進行處理:把異常問題,出現的原因輸出在控制台,同時結束程序

1.1 try...catch...finally處理格式

try {
    //可能出現問題的代碼,代碼量越少越好,虛擬機需要開辟新的問題處理這個問題
}catch(異常名稱) {
    //針對問題的處理
}finally {
    //釋放資源
} 
// 變形格式
try {
    //可能出現問題的代碼,try問題出現以后,將會去catch里面查找,但是不能繼續執行try里面的代碼
}catch(異常名稱) {    
    //異常名稱寫成Exception可以接收所有的異常,能明確盡量明確,針對問題的處理,需要有處理方式
}

例如:

   public static void main(String[] args) {
        int a = 20;
        int b = 0;
        
        try {
            System.out.println(a / b);
        }catch(ArithmeticException s) {
            System.out.println("除數不能為0");
        }
        System.out.println("over");
    }

JDK7異常處理新特性:

    public static void method2() {
        int a = 0;
        int b = 0;
        int[] arr = {1, 2, 3};
        try {
            System.out.println(a / b);
            System.out.println(arr[3]);
        }catch(ArithmeticException | ArrayIndexOutOfBoundsException  s){
            System.out.println("有問題");
        }
        System.out.println("over");

注意:異常必須是同級關系,不能夠是繼承關系,並且所有的異常執行同一種操作

異常的幾個常用方法:

public String getMessage():返回異常的消息字符串

public String toString():返回throwable的簡短描述,將由一下字符串拼接而成:

  此對象的類的名稱(全路徑名)

  ": "冒號和一個空格

  調用此對象getLocalizedMessage()方法的結果

public String getLocalizedMessage():創建throwable的本地化描述,子類可以重寫此方法,以便生成特定語言環境的消息,對於不重寫此方法的子類,將默認返回與getMessage()的結果

void printStackTrace():獲取異常類名和異常信息,以及異常出現在程序中的位置,返回void

void printStackTrace(PrintStream s):通常用該方法將異常的內容存儲到日志文件中,以便日后查看

    public static void main(String[] args) {
        String s = "2014-01";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        
        try {
            Date d = sdf.parse(s);
            System.out.println(d);
        } catch (ParseException e) {
            System.out.println(e.getMessage());
            System.out.println(e.toString());
            e.printStackTrace();
        }
        
    }

finally:finally控制的語句一定會得到執行,但是如果執行finally之前jvm退出,將不能執行

finally主要用於釋放資源,在IO流和數據庫的操作中會經常遇到,try...finally可以單獨使用

final:最終的意思,可以修飾類,成員變量,成員方法

修飾類:類不能夠被繼承

修飾變量:該變量是常量

修飾方法:方法不能夠被重寫

finalize:是Object類的一個方法,用於垃圾回收。

 

1.2 throws處理格式

特點:自身不能處理或者沒有權限處理,拋出后是編譯器的異常必須要處理,運行期可以不處理

    public static void main(String[] args) {
        System.out.println("今天的天氣很好");
        try {
            method();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("就是有點熱");
    }

    public static void method() throws ParseException {
        String s = "2015-11-20";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//不能處理或者沒有權限處理
        Date d = sdf.parse(s);
    }

1.3 throw以及與throws的區別

throws:

  用在方法聲明后面,后面跟的是異常的名稱

  可以跟多個異常類名稱,用逗號隔開

  表示拋出異常,由該方法的調用者來處理這個異常

  throws表示出現異常的一種可能性,並不一定會發生這些異常

throw:

  用在方法體中,跟的是異常的對象名

  只能拋出一個異常對象名

  表示拋出異常,由方法體內的語句處理

  throw則是拋出了異常,執行throw則一定是拋出了某種異常

    public static void main(String[] args) {
        method1();
        try {
            method2();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void method1() {
        int a = 10;
        int b = 0;
        if (b == 0) {
            throw new ArithmeticException();
        }else {
            System.out.println(a / b);
        }
    }
    
    public static void method2() throws Exception {
        int a = 10;
        int b = 0;
        if(b == 0) {
            throw new Exception();
        }else {
            System.out.println(a / b);
        }
    }

throws和try到底應該用哪個:

如果后續程序需要繼續運行就執行try

如果后續程序不需要繼續運行就執行throws

 

面試題:如果catch里面由return語句,那么finally里面的代碼是否會執行,如果會,請問在return 前還是在return 后:會,前,但是return 的返回路徑已經確定,准確的說finally在return 的中間

    public static void main(String[] args) {
        System.out.println(getInt());
    }
    
    public static int getInt() {
        int a = 10;
        try {
            System.out.println(a / 0);
            a = 20;
        }catch(ArithmeticException e) {
            System.out.println("出錯啦");
            a = 30;
            return a;
        }finally {
            System.out.println("到底在哪里呢");
            a = 40;
        }
        return a;
    }

程序運行結果:
出錯啦
到底在哪里呢
30

 1.4 自定義異常

public class MyException extends Exception{
    public MyException() {
        
    }
    
    public MyException(String message) {
        super(message);
    }
}
public class Teacher {
    public void check(int score) throws MyException {
        if(score > 100 || score < 0) {
            throw new MyException("分數必須在0到100之間");
        }else {
            System.out.println("分數沒有問題");
        }
    }
}

異常的注意事項:

1. 子類重寫父類方法時,子類的方法必須拋出相同的異常或者父類異常的子類,

2. 如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者它的子類的異常,子類不能夠拋出父類沒有的異常

3. 如果被重寫的方法沒有異常拋出,那么子類的方法絕對不能夠通過throw拋出異常,如果子類方法有異常發生,那么子類只能用try不能用throw

 

2. 文件操作

2.1 File類和構造方法

定義:文件或者目錄路徑名的抽象表現形式,未必真實存在

構造方法:一下三種方式的效果相同,一般采用第一種方法:

public File(String pathname):根據路徑得到一個File對象

public File(String parent, String child):根據一個目錄和一個子文件得到File對象

public File(File parent, String chile):根據一個父File對象和一個子文件/目錄得到File對象

2.2 成員方法

創建功能:

public boolean createNewFile():創建文件,如果存在,就不創建並返回false

public boolean mkdir():創建文件夾,如果存在,不創建並返回false

public boolean mkdirs():創建文件夾,如果父文件夾不存在,也會創建,多層。

注意:創建文件或者文件夾時需要選擇正確的方法。

如果沒有寫盤符文件,默認在項目文件路徑下

刪除文件:

public boolean delete():刪除文件或者文件夾,刪除最后一層,Java刪除時不走回收站,

           刪除文件夾時,只有是空文件夾只能刪除

重命名功能:

public boolean renameTo(File dest):重命名file文件夾成dest

                  路徑名相同重命名,不同時先剪切在重命名

判斷功能:

public boolean isDirectory():判斷是否是目錄

public boolean isFile():判斷是否是文件

public boolean exists():判斷是否存在

public boolean canRead():判斷是否可讀

public boolean isHidden():判斷是否隱藏

    public static void main(String[] args) {
        File file1 = new File("D:\\Wet_Download\\Xunlei_Download\\wangwangwang");
        System.out.println("mkdir:" + file1.mkdir());
        System.out.println("mkdir:" + file1.mkdir());

        File file2 = new File("D:\\Wet_Download\\Xunlei_Download\\xiaojingzi.txt");
        try {
            System.out.println("mkdir:" + file2.createNewFile());
        } catch (IOException e) {
            e.printStackTrace();
        }

        File file3 = new File("D:\\Wet_Download\\Xunlei_Download\\wyy\\xio.txt");
        System.out.println("mkdirs:" + file3.mkdirs());

        System.out.println("delete:" + file3.delete());
        System.out.println("delete:" + file3.delete());
        System.out.println("delete:" + file1.delete());
        System.out.println("delete:" + file2.delete());

        File file4 = new File("D:\\Wet_Download\\Xunlei_Download\\wyy\\hello.txt");
        File file5 = new File("D:\\Wet_Download\\Xunlei_Download\\wyy\\gulao.txt");
        System.out.println(file4.renameTo(file5));
        System.out.println("------------");

        File file6 = new File("D:\\Wet_Download\\Xunlei_Download\\wyy");
        System.out.println(file6.isDirectory());
        System.out.println(file6.isFile());
        System.out.println(file6.exists());
        System.out.println(file6.canRead());
        System.out.println(file6.canWrite());
        System.out.println(file6.isHidden());

    }

獲取功能:

public String getAbsolutePath():獲取絕對路徑

public String getPath():獲取相對路徑

public String getName():獲取名稱

public long length():獲取字節數

public long lastModified():獲取最后一次修改時間,毫秒值

    public static void main(String[] args) {
        File file = new File("D:\\Wet_Download\\Xunlei_Download\\wyy");
        
        System.out.println("getAbsolutePath:" + file.getAbsolutePath());
        System.out.println("getPath:" + file.getName());
        System.out.println("getName:" + file.getName());
        System.out.println("length:" + file.length());
        System.out.println("lastModified:" + file.lastModified());
        
        Date d = new Date(1533819207190l);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = sdf.format(d);
        System.out.println(s);
        
        Date da = new Date();    // 獲取現在的時間
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String st = sdf.format(da);
        System.out.println(st);
    }

插入:時間轉字符串以及字符串轉時間

// 時間轉字符串輸出:
        Date d = new Date(1533819207190l);    // 毫秒值
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = sdf.format(d);
        System.out.println(s);
        
        Date da = new Date();    // 獲取現在的時間
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String st = sdf.format(da);
        System.out.println(st);

// 字符串轉時間輸出:
                String s = "2015-11-20";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//不能處理或者沒有權限處理
        Date d = sdf.parse(s);            

高級獲取功能:

public String[] list():返回指定文件夾或文件字符串文件名數組

public File[] listFiles():返回指定文件夾或文件的文件類數組

    public static void main(String[] args) {
        File file = new File("D:\\Wet_Download");
        
        String[] st = file.list();
        System.out.println(Arrays.toString(st));
        
        File[] fi = file.listFiles();
        System.out.println(Arrays.toString(fi));
    }

文件名稱過濾器:

public String[] list(FilenameFilter filter):根據過濾器返回指定文件夾或文件字符串文件名數組

public File[] listFiles(FilenameFilter filter):根據過濾器返回指定文件夾或文件的文件類數組

    public static void main(String[] args) {
        File file = new File("D:\\Wang_File\\Home_Work\\dynamic_convolution");
        String[] strArray = file.list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
/*                File fil = new File(dir, name);
                if(fil.isFile()) {
                    if(name.endsWith(".jpg")) {
                        return true;
                    }
                }
                return false;*/
                return new File(dir, name).isFile() && name.endsWith(".jpg");
            }
        });
        System.out.println(Arrays.toString(strArray));
    }

 

3. IO流

3.1 遞歸

遞歸:方法內部調用方法本身的現象

注意事項

1. 遞歸需要有出口,否則就是死遞歸

2. 遞歸的次數不能夠太多,否則就會導致內存溢出

3. 構造方法不能夠遞歸調用

    public static int calc(int n) {
        if(n == 1) {
            return 1;
        }else {
            return n * calc(n - 1);
        }
    }
    public static void deleteFolder(File srcFolder) {
        File[] fileArray = srcFolder.listFiles();
        for(File file : fileArray) {        // 刪除文件
            if(file.isDirectory()) {
                deleteFolder(file);
            }else {
                System.out.println(file.getName() + "----" + file.delete());
            }
        }
        System.out.println(srcFolder.getName() + "----" + srcFolder.delete());    // 刪除文件夾
    }

3.2 java IO流的分類:

按照流向:輸入流:寫數據,輸出流:讀數據

按照數據類型:字節流:都可以使用字節流來傳輸

輸入字節流:讀取數據  InputStream

輸出字節流:寫出數據  OutputStream

字符流:如果是文本類型的數據,可以使用記事本打開,就可以采用字符流來傳輸

輸入字符流:讀取數據  Reader

輸出字符流:寫出數據  Writer

3.2.1 OutputStream

FileOutputStream的構造方法:

FileOutputStream(File file):

FileOutputStream(String name):調用系統功能創建文件,創建fos對象,把fos對象指向這個文件

FileOutputStream(String name, boolean append):true時追加

FileOutputStream(File file, boolean append):true時追加

 

close():

A 讓流對象變成垃圾,這樣就可以被垃圾回收器回收了

B 通知系統去釋放文件相關的資源

public void write(int b):

public void write(byte[] b):

public void write(byte[] b, int off, int len):

    public static void main(String[] args) throws IOException {
        OutputStream fos = new FileOutputStream("fos.txt");
        fos.write("hello,Io".getBytes());
        fos.write("xiaojingzi".getBytes());
        fos.write(382);
        fos.write("xiaojingzi".getBytes(), 2, 3);
        byte[] bys = {'a', 'b', 'c'};
        fos.write(bys);
        fos.close();    // A 讓流對象變成垃圾,這樣就可以被垃圾回收器回收了 B 通知系統去釋放與該文件有關的資源
    }

加入異常處理的字節輸出流操作

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("fos1.txt");
            fos.write("wa".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close(); // 只有fos不是null才能夠調用
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

3.2.2 OutputStream

構造方法:

FileInputStream(File file):

FileInputStream(FileDescriptor fdObj):

FileInputStream(String name):

    public static void main(String[] args) throws IOException {
        FileInputStream fos = new FileInputStream("fos.txt");
        int by = 0;
        while((by = fos.read()) != -1) {
            System.out.print((char)by);
        }
    }

文件的復制:可以復制中文,IO流先讀再寫,沒有做任何轉換,所以可以做正常顯示

    public static void main(String[] args) throws IOException {
        FileInputStream file = new FileInputStream("fos.txt");
        FileOutputStream fos = new FileOutputStream("b.txt");
        int by = 0;
        while((by = file.read()) != -1) {
            fos.write(by);
        }
        fos.close();
        file.close();
    }

!字節流適用於任意格式的文件

高效率讀取:

    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("fos.txt");
        byte[] bys = new byte[5];
        int len = 0;
        while((len = fis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }
    }

 最終版:數組的長度一般是1024或者1024的整數倍

    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("fos.txt");
        byte[] bys = new byte[1024];
        int len = 0;
        while((len = fis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }
    }

3.3 字節緩沖流

字節流讀寫一個數組的速度明顯比一次讀寫一個字節的速度快很多,這是加入了數組這樣的緩沖區效果,java在本身設計時考慮到這樣的設計思想,提供了字節緩沖區流

字節緩沖輸出流:BufferedOutputStream

構造方法:一般使用默認的緩沖器大小即可

BufferedOutputStream(OutputStream out):使用默認輸出緩沖區的緩沖字符輸出流

BufferedOutputStream(OutputStream out, int size):指定輸出緩沖區的緩沖字符輸出流

字節緩沖輸入流:BufferedInputStream

BufferedInputStream(InputStream out):使用默認輸出緩沖區的緩沖字符輸出流

BufferedInputStream(InputStream out, int size):指定輸出緩沖區的緩沖字符輸出流

例:傳輸視頻文件:

    public static void main(String[] args) throws IOException {
        BufferedInputStream buf = new BufferedInputStream(new FileInputStream("D:\\Wet_Download\\Baiduyun_Download\\day20\\avi\\20.01_IO流(遞歸概述和注意事項).avi"));
        BufferedOutputStream bof = new BufferedOutputStream(new FileOutputStream("D:\\Wet_Download\\copy.avi"));
        
        byte[] bys = new byte[1024];
        int len;
        while((len = buf.read(bys)) != -1) {
            bof.write(bys, 0, len);
        }
    }

3.4 轉換流

字符流=字節流+編碼表

編碼表:由現實世界額字符和對應的數值組成的一張表

ASCII碼表,最高位為符號位,其余為數值位

ISO-8859-1,拉丁碼表,8位表示一個數據

gb2313:中文編碼表

gbk:

Unicode:國際標准碼,融合了一個文字,所有文字都用兩個字節表示,java使用的都是Unicode

Utf-8:最多用三個字節來表示一個字符,使用盡可能少的字節數來表示一個字符

String類中的編碼與解碼問題:

String(byte[] bytes, String charsetName):通過指定的字符集解碼字節數組
byte[] getBytes(string charsetName):使用指定的字符集合將字符串編碼為字節數組

windows:默認本地系統編碼為GBK

 

    public static void main(String[] args) throws UnsupportedEncodingException {
        byte[] bys = "你好".getBytes("GBK");
        System.out.println(Arrays.toString(bys));//[-60, -29, -70, -61]
        String ss = new String(bys, "GBK");
        System.out.println(ss);
        
        byte[] bts = "你好".getBytes("UTF-8");
        System.out.println(Arrays.toString(bts));//[-28, -67, -96, -27, -91, -67]
        String bs = new String(bts, "UTF-8");
        System.out.println(bs);
    }

3.4.1 字符流(轉換流)

3.4.1 OutputStreamWriter

構造方法:

OutputStreamWriter(OutputStream out):創建一個使用默認字符編碼的OutputStreamWriter

OutputStreamWriter(OutputStream out, Charset cs):創建一個使用給定字符集的OutputStreamWriter

OutputStreamWriter(OutputStream out, CharsetEncoder enc):創建一個使用給定字符集編碼器的OutputStreamWriter

OutputStreamWriter(OutputStream out, Striing charsetName):創建一個使用命名字符集的OutputStreamWriter

    public static void main(String[] args) throws IOException {
        OutputStreamWriter osv = new OutputStreamWriter(new FileOutputStream("xiaojignzi.txt"), "UTF-8");
        osv.write("中國");
        osv.close();
    }

接口方法:

public void write(int c):寫一個字符

public void write(char[] cbuf):寫一個字符數組

public void write(char[] cbuf,int off, int len):寫一個字符數組的一部分

public void write(Striing str):寫一個字符串

public void write(String str, int off, int len):寫一個字符串的一部分

    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("xiaojignzi.txt"));
        char[] ch = {'a', 'b', 'c'};
        
        osw.write("小鏡子");
        osw.write(ch);
        osw.write(ch, 0, 1);
        osw.write("小君子", 0, 1);
        osw.flush();
        
        osw.close();    //先刷新后關閉
    }

3.4.2 InputStreamReader

構造方法:

InputStreamReader(InputStream in):創建一個使用默認字符集的InputStreamReader

InputSteamReader(InputStream in, Charset cs):創建一個使用給定字符集的InputStreamReader

InputStreamReader(InputStream in, CharsetDecoder dec):創建一個使用給定字符集編碼器的InputStreamReader

InputStreamReader(InputStream in, String charsetName):創建一個使用命名字符集的InputStreamReader

    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("xiaojignzi.txt"), "GBK");
        int ch = 0;
        while((ch = isr.read()) != -1) {
            System.out.print((char)ch);
        }
        isr.close();
    }

使用什么編碼方式寫的數據,則以哪種編碼方式寫數據

接口方法:

public int read():一次讀取一個字符

public read(char[] chs):一次讀取一個字符數組

    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("xiaojingzi.txt"), "UTF-8");
        osw.write("xiaojingzi\r\n微信開發者工具");
        osw.close();
        InputStreamReader ops = new InputStreamReader(new FileInputStream("xiaojingzi.txt"), "UTF-8");
        OutputStreamWriter ors = new OutputStreamWriter(new FileOutputStream("xiaojunzi.txt"), "UTF-8");
        
        char[] ch = new char[1024];
        int len = 0;
        while((len = ops.read(ch)) != -1) {
            ors.write(ch, 0, len);
        }
        ors.close();
        ops.close();
    }

3.4.3 FileWriter:采用本地的編碼方式

OutputStreamWriter的子類

構造方法:

FileWriter(File file):File指定文件名

FileWriter(File file, boolean append):File指定文件名,並確定是否追加

FileWriter(FileDescriptor fd):

FileWriter(String fileName):用String指定文件名

FileWriter(String fileName, boolean append):用String指定文件名,並確定是否追加

3.4.4 FileReader:采用本地的編碼方式

InputStreamReader的子類

構造方法:

FileReader(File file):指定的file讀取

FileReader(FileDescriptor fd):給定的FileDescriptor讀取

FileReader(String fileName):給出讀取文件的名稱

    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("D:\\Wet_Download\\Baiduyun_Download\\04.Python3.5 裝飾器編程 18課\\源碼\\內置方法.py");
        FileWriter fw = new FileWriter("D:\\wang.txt");
        
        char[] ch = new char[1024];
        int len = 0;
        while((len = fr.read(ch)) != -1) {
            fw.write(ch, 0, len);
        }
        fw.close();
        fr.close();
    }

3.4.5 字符緩沖輸出流:BufferedWriter,如果是追加寫,FileWriter("文件名", true)

構造方法:

BufferedWriter(Writer in):創建使用默認大小的輸入緩沖區緩沖區字符輸入流

BufferedWriter(Writer in, int sz):創建使用指定大小的輸入緩沖區字符輸入流

接口方法:

public void newLine():根據系統來產生一個換行符

3.4.6 字符緩沖輸入流:BufferedReader

構造方法:

BufferedReader(Reader in):創建使用默認大小的輸入緩沖區緩沖區字符輸入流

BufferedReader(Reader in, int sz):創建使用指定大小的輸入緩沖區字符輸入流

接口方法:

public String readLine():一次讀取一行數據

不包含換行符,讀不到新行放回null

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new FileReader("xiaojingzi.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("wanwang.txt"));
        char[] chs = new char[1024];
        int len = 0;
        while((len = br.read(chs)) != -1) {
            bw.write(chs, 0, len);
        }
        br.close();
        bw.close();
    }

 按照行復制文件的案例:

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("xiaojingzi.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("hh.txt"));
        String line = null;
        while((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
    }

 

復制多級文件的案例

package dat_20;

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

public class MoreFile {
    public static void main(String[] args) throws IOException {
        File srcFile = new File("D:\\簡歷");
        File destFile = new File("D:\\move");
        System.out.println(destFile.mkdir());
        
        copyFolder(srcFile, destFile);
    }
    
    public static void copyFolder(File srcFile, File destFile) throws IOException {
        if(srcFile.isDirectory()) {
            File newFolder = new File(destFile, srcFile.getName());
            newFolder.mkdir();
            File[] fileArray = srcFile.listFiles();
            for(File file : fileArray) {
                copyFolder(file, newFolder);
            }
        }else {
            File newFile = new File(destFile, srcFile.getName());
            copyFile(srcFile, newFile);
        }
    }
    
    public static void copyFile(File srcFile, File destFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        
        byte[] bys = new byte[1024];
        int len = 0;
        while((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }
        bos.close();
        bis.close();
    }
}

 學生類根據總分從分高到低排序:

    public static void main(String[] args) throws IOException{
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){

            @Override
            public int compare(Student o1, Student o2) {
                int num1 = o2.getSum() - o1.getSum();
                int num2 = num1 == 0 ? o2.getChinese() - o1.getChinese() : num1;
                int num3 = num2 == 0 ? o2.getMath() - o1.getMath() : num2;
                int num4 = num3 == 0 ? o2.getName().compareTo(o1.getName()) : num3;
                return num4;
            }
            
        });
        for(int x = 0; x < 5; x++){
            Student st = new Student();
            Scanner sc = new Scanner(System.in);
            System.out.println("please input student grade" + x);
            System.out.println("please input student name");
            st.setName(sc.nextLine());
            System.out.println("please input chinese grade");
            st.setChinese(sc.nextInt());
            System.out.println("please input math grade");
            st.setMath(sc.nextInt());
            System.out.println("please input english grade");
            st.setEnglish(sc.nextInt());
            ts.add(st);
        }
        
        BufferedWriter bw = new BufferedWriter(new FileWriter("Student"));
        bw.write("學生成績如下:");
        bw.newLine();
        bw.flush();
        bw.write("姓名,語文成績,數學成績,英語成績");
        bw.newLine();
        bw.flush();
        for(Student s : ts){
            StringBuilder sb = new StringBuilder();
            sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",").append(s.getEnglish());
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }
        bw.close();
        System.out.println("學生信息存儲完畢");
    }

模擬BufferedReader 的readLine()功能

public class MyBufferedReader {
    private Reader r;
    
    public MyBufferedReader(Reader r){
        this.r = r;
    }
    
    public String readLine() throws IOException{
        StringBuffer sb = new StringBuffer();
        int ch = 0;
        while((ch = r.read()) != -1){
            if(ch == '\r'){
                continue;
            }else if(ch == '\n'){
                return sb.toString();
            }else{
                sb.append((char)ch);
            }
        }
        
        if(sb.length() > 0){
            return sb.toString();
        }
        
        return null;
    }
    
    public void close() throws IOException{
        this.r.close();
    }
}

3.4.7 LineNumberReader(BufferedReader的子類)

int getLineNumber():獲取行號

void setLineNumber(int):設置行號

    public static void main(String[] args) throws IOException{
        LineNumberReader lnr = new LineNumberReader(new FileReader("s"));
        lnr.setLineNumber(10);
        String line = null;
        while((line = lnr.readLine()) != null){
            System.out.println(lnr.getLineNumber() + ":" + line);
        }
        lnr.close();
    }

3.4.8 為了保證文件只創建一次,可以使用靜態代碼塊

private static File file = new File("文件名");
static {
         try{
             file.createNewFile();
         }catch(IOException e){
             System.out.println("創建文件夾失敗");
    } }

 3.5 操作基本數據類型的流

3.5.1 DataInputStream:數據輸出流允許應用程序將適當方式將基本Java數據類型輸入流中,應用數據可以使用數據輸入流將數據讀入

構造方法:DataOutputStream(OutputStream out):創建一個新的數據輸入流,將數據寫入指定基礎輸出流

3.5.2 DataOutputStream:數據輸出流使應用程序以便攜式方式將原始Java數據類型寫入輸出流。 然后應用程序可以使用數據輸入流來讀取數據。

構造方法:DataInputStream(InputStream input):創建一個新的數據輸出流,將數據讀出

public static void main(String[] args) throws IOException{
        //write();
        read();
    }
    
    public static void write() throws IOException{
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));
        dos.writeByte(10);
        dos.writeShort(100);
        dos.writeInt(1000);
        dos.writeChar('a');
        dos.writeFloat(23.878f);
        dos.writeDouble(343.38);
    }
    
    public static void read() throws IOException{
        DataInputStream dip = new DataInputStream(new FileInputStream("dos.txt"));
        byte b = dip.readByte();
        short s = dip.readShort();
        int i = dip.readInt();
        char c = dip.readChar();
        float f = dip.readFloat();
        double d = dip.readDouble();
        
        dip.close();
        
        System.out.println((int)c);
    }

3.6 內存操作流

操作字節數組:

ByteArrayInputStream:包含了一個內部緩沖區,該緩沖器可以從流中讀取字節,內部計數器跟蹤read方法要提供的下一個字節,關閉ByteArrayInputStream無效,此類中的方法在關閉此流后仍可以被調用,而不會產生任何的IOException.

ByteArrayOutputStream:此類實現了一個輸出流,其中的數據被寫入一個byte數組,緩沖區會隨着數據的不斷寫入自動增長,可以使用toByteArray()和toString()獲取數據

操作字符數組:

CharArrayReader

CharArrayWrite

操作字符串:

StringReader

StringWriter

    public static void main(String[] args) throws IOException{
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        
        for(int x = 0; x < 20; x++){
            baos.write(("hello" + x).getBytes());
        }
        
        byte[] bys = baos.toByteArray();
        
        System.out.println(Arrays.toString(bys));
        //不需要釋放資源
        ByteArrayInputStream bais = new ByteArrayInputStream(bys);
        
        int by = 0;
        while((by = bais.read()) != -1){
            System.out.print((char)by);
        }
    }

3.7 打印流:

字節打印流:PrintStream

字符打印流:PrintWriter:

特點:

1. 只能操作目的地,不能操作數據

2. 可以操作任意類型的數據

3. 如果啟動了自動刷新,可以自動刷新

4. 可以操作文件的流

public static void main(String[] args) throws IOException{
        PrintWriter pw = new PrintWriter(new FileWriter("pw.txt"), true);//帶true實現了自動刷新的功能,但是需要調用println方法才可以
        pw.write("hello");
        pw.write("world");
        pw.write("java");
        //pw.close();
        pw.print(true);
        pw.print(100);
        pw.print("heool");
        pw.print("wangjing");
        pw.println("xiaojingzi");    //實現了換行
        /*println相當於實現了
         *write();
         *newLine();
         *flush();
         *三種方法的操作
         */
        pw.close();
    }

使用打印流實現復制文本文件

    public static void main(String[] args) throws IOException{
        /*BufferedWriter bw = new BufferedWriter(new FileWriter("copy.java"));
        BufferedReader br = new BufferedReader(new FileReader("Student"));
        String line = null;
        while((line = br.readLine()) != null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        br.close();*/
        BufferedReader br = new BufferedReader(new FileReader("Student"));
        PrintWriter pw = new PrintWriter(new FileWriter("copy.java"), true);
        String line = null;
        while((line = br.readLine()) != null){
            pw.println(line);
        }
        br.close();
        pw.close();
    }

 3.8 標准輸入輸出流

System類中有兩個成員變量:

public static final InputStream in "標准"輸入流

public static final PrintStream out "標准"輸出流

InputStream is = System.in;

PrintStream ps = System.out;

public static void main(String[] args){
        //本質是把IO流輸出到控制台(默認輸出設備控制台,輸入設備是鍵盤)
        System.out.println("helloworld");
        
        PrintStream ps = System.out;
        ps.println("xiaojignzi");
        //ps.print();    報錯
        ps.println();
    }

鍵盤錄入數據:

A:main方法的args接收數據

B:Scanner(JDK5以后)

  Scanner sc = new Scanner(System.in)

  String s = sc.nextLine();

注:Scanner容易出現的小問題

先獲取Int再獲取字符串時,導致輸入一個Int以后便不需要再輸入,然后字符串讀取的只是回車符。

 C:通過字符緩沖流包裝標准的輸入流實現:BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); /*上述的語句等價為
         * InputStream is = System.in;
         * InputStreamReader isr = new InputStreamReader(is);
         * BufferedReader br = new BufferedReader(isr);
         */
        System.out.println("請輸入一個字符串");
        String line = br.readLine();
        System.out.println("您輸入的字符串是:" + line);
        
        System.out.println("請輸入一個整數");
        int i = Integer.parseInt(br.readLine());
        System.out.println("您輸入的整數是:" + i);
    }

輸出數據到控制台

    public static void main(String[] args) throws IOException{
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        /*
         * PrintStream ps = System.out;
         * OutputStream os = ps;        (OutputStream os = System.out;)   多態
         * OutputStreamWriter osw = new OutputStreamWriter(os)
         * BufferedWriter bw = new BufferedWriter(osw);
         */
        bw.write("hello");
        bw.newLine();
        bw.write("world");
        bw.newLine();
        bw.write("xiaojignzi");
        bw.flush();
    }

3.9 RandomAccessFile

RandomAccessFile類不屬於任何流,是Object類的子類,融合了InputStream和OutputStream的功能,支持對隨機訪問文件的讀取和寫入

有四種模式,常用是rw可以同時讀寫,文件不存在將嘗試創建

    public static void main(String[] args) throws IOException {
        write();
        read();
    }

    public static void read() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
        int i = raf.readInt();
        System.out.println(i);
        System.out.println("當前文件的指針是:" + raf.getFilePointer()); //4 int 類型數據占四個字節
        
        char ch = raf.readChar();
        System.out.println(ch);
        System.out.println("當前文件的指針位置是:" + raf.getFilePointer());  //6 char 類型數組占兩個字節
        
        String s = raf.readUTF();
        System.out.println(s);
        System.out.println("當前文件的指針位置是:" + raf.getFilePointer()); //14 先讀取兩個字節,再讀取后面的字節
        
        raf.seek(4);
        ch = raf.readChar();
        System.out.println(ch);    //a
        raf.close();
    }

    public static void write() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
        raf.writeInt(100);
        raf.writeChar('a');
        raf.writeUTF("小哈");
        raf.close();
    }

3.10 SequenceInputStream表示其它輸入流的邏輯串聯,它從輸入流的有序集合開始,並從第一個輸入流開始讀取,直到文件的末尾,接着從第二個輸入流讀取,依次類推,直到最后一個輸入流文件的末尾為止  

合並流讀取兩個文件的內容復制到一個文件中

    public static void main(String[] args) throws IOException{
        InputStream is1 = new FileInputStream("dos.txt");
        InputStream is2 = new FileInputStream("pw.txt");
        SequenceInputStream sis = new SequenceInputStream(is1, is2);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy"));
        
        byte[] bys = new byte[1024];
        int len = 0;
        while((len = sis.read(bys)) != -1){
            bos.write(bys, 0, len);
        }
        bos.close();
        sis.close();
    }

合並多個文件:

    public static void main(String[] args) throws IOException{
        Vector<InputStream> v = new Vector<InputStream>();
        InputStream s1 = new FileInputStream("copy");
        InputStream s2 = new FileInputStream("dos.txt");
        InputStream s3 = new FileInputStream("copy.java");
        v.add(s1);
        v.add(s2);
        v.add(s3);
        Enumeration<InputStream> en = v.elements();
        SequenceInputStream sis = new SequenceInputStream(en);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("xiaojigzi"));
        
        byte[] byt = new byte[1024];
        int len = 0;
        while((len = sis.read(byt)) != -1){
            bos.write(byt, 0, len);
        }
        
        sis.close();
        bos.close();
    }

 3.11 序列化與反序列化流

序列化流:ObjectOutputStream:將JAVA對象的基本數據類型寫入OutputStream,可以使用ObjectInputStream讀取(重構對象),可以使用文件來實現對象的持久存儲,如果流是網絡套接字節流,可以再另一台主機或者另一個進程中重構對象

反序列化流:ObjectInputStream

NotSerializableException:未序列化異常

類通過實現java.io.Serializable 接口以啟用序列化功能,未實現此接口無法進行任何的序列化和反序列化。該接口中沒有任何的方法需要實現。沒有方法的接口被稱為標記接口。

private static final long serialVersionUID = 1087170578858793875L;產生序列化

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        //write();
        read();
    }
    
    public static void write() throws IOException, IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("xiao"));
        Person p = new Person("wangjing", 20);
        oos.writeObject(p);
        oos.close();
    }
    
    public static void read() throws IOException, ClassNotFoundException{
        ObjectInputStream oos = new ObjectInputStream(new FileInputStream("xiao"));
        Object obj = oos.readObject();
        oos.close();
        System.out.println(obj);    // 多態調用的是子類的方法
    }

如何不序列化對象的成員變量:使用transient修飾  private transient int age;

3.12 Properties類:屬性集合類,是一個可以和IIO流相結合的集合類

表示一個持久的屬性集,Properties可以保存在流中或者從流中加載,屬性列表中每個鍵和對應的值都是一個字符串

Properties作為map集合使用

    public static void main(String[] args){
        Properties prop = new Properties();
        prop.put("it001", "hello");
        prop.put("it002", "world");
        prop.put("it003", "java");
        
        
        Set<Object> set = prop.keySet();
        for(Object key : set){
            Object value = prop.get(key);
            System.out.println(key + "-----" + value);
        }
    }

Properties的特殊功能使用

public Object setProperty(String key, String value):添加元素

public String getProperty(String key):獲取元素

public Set<String> stringPropertyNames():獲取所有鍵的集合

    public static void main(String[] args){
        Properties prop = new Properties();
        prop.setProperty("張三", "30");
        prop.setProperty("李四", "40");
        prop.setProperty("王五", "30");
        
        Set<String> set = prop.stringPropertyNames();
        for(String key : set){
            String value = prop.getProperty(key);
            System.out.println(key + "----" + value);
        }
    }

Properties與IO流結合使用

public void load(Reader reader):把文件中的數據讀取到集合中

public void store(Writer writer, String comments):把集合中的數據存儲到文件

    public static void main(String[] args) throws IOException{
        myStore();
    }
    
    public static void myLoad() throws IOException{
        Properties prop = new Properties();
        Reader r = new FileReader("prop.txt");
        prop.load(r);
        r.close();
        System.out.println("prop" + prop);
    }
    
    public static void myStore() throws IOException{
        Properties prop = new Properties();
        prop.setProperty("wangjing", "30");
        prop.setProperty("ixaoxiao", "10");
        prop.setProperty("wang", "30");
        Writer w = new FileWriter("wang.txt");
        prop.store(w, "heoolworld");    //"heoolworld"是注釋
        w.close();
    }

判斷文件中是否有指定的鍵,如果有就修改值

    public static void main(String[] args) throws IOException{
        Properties prop = new Properties();
        Reader r = new FileReader("wang.txt");
        prop.load(r);
        r.close();
        
        Set<String> set = prop.stringPropertyNames();
        for(String key : set){
            if("wang".equals(key)){
                prop.setProperty(key, "100");  // 替換
                break;
            }
        }
        
        Writer w = new FileWriter("wang.txt");
        prop.store(w, null);
        w.close();
    }

3.13 NIO包下的IO流

JDK4出現NIO,新IO和傳統的IO有相同的目的,都是用於進行輸入輸出的額,但新的IO使用了不同的方式來處理輸入輸出的,采用內存映射文件的方式。將文件或者文件的一段區域映射到內存中,就可以像訪問內存一樣的來訪問文件了,這樣的效率比舊的IO要高很多。

Path:路徑

Paths:有一個靜態方法返回一個路徑

public static Path get(URI uri)

Files:提供了靜態方法供我們使用

public static long copy(Path source, OutputStream out)

public static Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options)

    public static void main(String[] args) throws IOException, IOException{
        Files.copy(Paths.get("prop.txt"), new FileOutputStream("copy.java"));    // 復制文件
        ArrayList<String> array = new ArrayList<String>();
        array.add("hello");
        array.add("wrold");
        array.add("java");
        Files.write(Paths.get("array.txt"), array, Charset.forName("GBK"));
    }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM