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")); }