java8--IO(java疯狂讲义3复习笔记)
?產生文件
File file = new File("abc.txt");if(!file.exists()){System.out.println(file.exists());file.createNewFile();}System.out.println(file.getAbsolutePath());?
關于臨時文件
1).放在指定目錄,此時已項目為默認目錄
File file = File.createTempFile("defaultTmp","tmpp",new File("./"));System.out.println(file.getAbsolutePath());--------------------------------------------------
/Users/liuxin/work/workspace2/learnJava/./defaultTmp5487876755372558069tmpp
2).放在默認目錄
File file = File.createTempFile("defaultTmp",".tmpp");System.out.println(file.getAbsolutePath());------------------------------------------------------------------------ /var/folders/f9/x95426d95ng7wgy7f7yccj3w0000gn/T/defaultTmp1175907986750188229tmpp3).虛擬機退出時刪除臨時文件
File file = File.createTempFile("defaultTmp",".tmpp");file.deleteOnExit();System.out.println(file.getAbsolutePath());4).關于后綴
File testFile = new File("testFile");if(!testFile.exists()){testFile.mkdirs();}testFile.deleteOnExit();File file = File.createTempFile("defaultTmp","tmpp");System.out.println(file.getAbsolutePath());File file2 = File.createTempFile("defaultTmp2",".tmpp",testFile);System.out.println(file2.getAbsolutePath());File file3 = File.createTempFile("defaultTmp3",null,testFile);System.out.println(file3.getAbsolutePath());======================================= /var/folders/f9/x95426d95ng7wgy7f7yccj3w0000gn/T/defaultTmp5296324826431648502tmpp /Users/liuxin/work/workspace2/learnJava/testFile/defaultTmp21551336802243345058.tmpp /Users/liuxin/work/workspace2/learnJava/testFile/defaultTmp33930717872920538957.tmp?
操作目錄
1.查看目錄下的所有文件
File currentFile = new File(".");System.out.println(currentFile.getAbsolutePath());for(File file : currentFile.listFiles()){System.out.println(file.getName());}?
getParent()的使用方法
?
File file = new File("."); System.out.println(file.getAbsolutePath()); System.out.println(new File(file.getAbsolutePath()).getParent());----------------------- /Users/liuxin/work/workspace2/learnJava/. /Users/liuxin/work/workspace2/learnJavagetParent()只有在定義文件時有路徑時才起作用.?
15.2 流
字節流主要由InputStream和OutputStream作為基類,而字符流則主要由Reader和Writer作為基類.
字節流操作的數據單元是8位的字節,而字符流操作的數據單元是16位的字符
節點流和處理流,節點流是低級流,直接跟數據源相接.處理流(也叫包裝流)把節點流包裝了一層,屬于修飾器設計模式.
處理流的功能主要體現在以下兩個方面:
1.性能的提高:主要以增加緩沖的方式來提高輸入輸出的效率
2.操作的便捷:處理流可能提供了一系列便捷的方法來一次輸入輸出大批量的內容,而不是輸入/輸出一個或多個水滴
處理流可以嫁接在任何已存在的流的基礎上.
15.3.1 InputStream和Reader
InputStream和Reader是所有輸入流的抽象基類,本身并不能創建實例來執行.
讀取文件的demo
public static void testFile() throws IOException{// 創建字節輸入流FileInputStream fis = new FileInputStream("a.txt");// 創建一個長度為1024的“竹筒”byte[] bbuf = new byte[1024];// 用于保存實際讀取的字節數int hasRead = 0;// 使用循環來重復“取水”過程while ((hasRead = fis.read(bbuf)) > 0 ){// 取出“竹筒”中水滴(字節),將字節數組轉換成字符串輸入!System.out.print(new String(bbuf , 0 , hasRead ));}// 關閉文件輸入流,放在finally塊里更安全 fis.close();}?
關于fileFilter
?
File file = new File(".");String[] nameList = file.list((dir, name) -> name.endsWith(".java")|| new File(name).isDirectory());for(String name : nameList){System.out.println(name);}================================ .settings a bin lib result sqlModify src testFile?
15.2 理解java的IO流
用字節流讀取文件并打印
public static void testFile2() throws IOException{// 創建字節輸入流FileInputStream fis = new FileInputStream("a.txt");//讀取一個字節,返回的是int,所以要用char強轉System.out.println((char)fis.read());// 創建一個長度為1024的“竹筒”byte[] bbuf = new byte[1024];//讀取5個字節,放在bbuf的index為10的位置fis.read(bbuf,10,10); // 從bbuf中index為10的位置讀取5個字節構成字符串System.out.println(new String(bbuf , 10, 5));//轉換成String后,byte[]不變System.out.println(new String(bbuf , 10, 5));// 用于保存實際讀取的字節數int hasRead = 0;// 使用循環來重復“取水”過程while ((hasRead = fis.read(bbuf)) > 0 ){//重新賦值后,byte[]會改變System.out.println(new String(bbuf , 10, 5));// 取出“竹筒”中水滴(字節),將字節數組轉換成字符串輸入!System.out.println("==============================================");String test = new String(bbuf , 0 , hasRead );System.out.println(test);System.out.println("=================="+new String(bbuf , 0 , hasRead ).length()+"============================");}// 關閉文件輸入流,放在finally塊里更安全 fis.close();} 打印結果如下< ?xml ?xml ncodi ============================================== on="1.0" encoding="UTF-8"?> <projectDescription><name>learnJava</name><comment></comment><projects></projects><buildSpec><buildCommand><name>org.eclipse.jdt.core.javabuilder</name><arguments></arguments></buildCommand></buildSpec><natures><nature>org.eclipse.jdt.core.javanature</nature></natures> </projectDescription>我很好啊,看看需不要utf-8 ==================373============================ public static void testFile3() {try(// 創建字符輸入流FileReader fr = new FileReader("a.txt")){// 創建一個長度為32的“竹筒”char[] cbuf = new char[32];System.out.println(fr.read(cbuf,0,32));System.out.println(new String(cbuf));// 用于保存實際讀取的字符數int hasRead = 0;// 使用循環來重復“取水”過程while ((hasRead = fr.read(cbuf)) > 0 ){// 取出“竹筒”中水滴(字符),將字符數組轉換成字符串輸入! // System.out.print(new String(cbuf , 0 , hasRead));System.out.print(new String(cbuf));}}catch (IOException ex){ex.printStackTrace();}}
?
outPutStream 和 Writer
public static void testFileWriter() {//這里a.txt可以不存在,如果不存在回自動生成,但是沒搞明白怎么設置編碼格式try(FileWriter fw = new FileWriter("a.txt")){fw.write("錦瑟 - 李商隱\r\n");fw.write("錦瑟無端五十弦,一弦一柱思華年。\r\n");fw.write("莊生曉夢迷蝴蝶,望帝春心托杜鵑。\r\n");fw.write("滄海月明珠有淚,藍田日暖玉生煙。\r\n");fw.write("此情可待成追憶,只是當時已惘然。\r\n");}catch (IOException ioe){ioe.printStackTrace();}}
?
15.4 輸入輸出流體系
處理流:構造參數是已經存在的流.
節點流:構造參數是物理IO節點
處理流的用法
public static void PrintStream() {try(FileOutputStream fos = new FileOutputStream("a.txt");PrintStream ps = new PrintStream(fos)){// 使用PrintStream執行輸出ps.println("普通字符串");// 直接使用PrintStream輸出對象ps.println(new LearnIO());}catch (IOException ioe){ioe.printStackTrace();}}輸出結果
普通字符串 learnIO.LearnIO@677327b6在使用了處理流包裝了底層節點之后,關閉輸入/輸出流資源時,只要關閉最上層的處理流即可。關閉最上層的處理流時,系統會自動關閉被該處理流包裝的節點流。
字符串流的用法,似乎沒什么用,等發現用處再補充
public static void stringNodeTest() {String src = "從明天起,做一個幸福的人\n"+ "喂馬,劈柴,周游世界\n"+ "從明天起,關心糧食和蔬菜\n"+ "我有一所房子,面朝大海,春暖花開\n"+ "從明天起,和每一個親人通信\n"+ "告訴他們我的幸福\n";char[] buffer = new char[32];int hasRead = 0;try(StringReader sr = new StringReader(src)){// 采用循環讀取的訪問讀取字符串while((hasRead = sr.read(buffer)) > 0){System.out.print(new String(buffer ,0 , hasRead));}}catch (IOException ioe){ioe.printStackTrace();}try(// 創建StringWriter時,實際上以一個StringBuffer作為輸出節點// 下面指定的20就是StringBuffer的初始長度StringWriter sw = new StringWriter()){// 調用StringWriter的方法執行輸出sw.write("有一個美麗的新世界,\n");sw.write("她在遠方等我,\n");sw.write("哪里有天真的孩子,\n");sw.write("還有姑娘的酒窩\n");System.out.println("----下面是sw的字符串節點里的內容----");// 使用toString()方法返回StringWriter的字符串節點的內容System.out.println(sw.toString());}catch (IOException ex){ex.printStackTrace();}}?
15.4.3 轉換流
InputStreamReader :將字節輸入流轉換成字符輸入流
OutputStreamWriter:將字節輸出流轉換成字符輸出流
經過測試,下面這個程序是有一定問題的,用輸入法的時候,會重復輸出好多遍
public static void KeyinTest() {try(// 將Sytem.in對象轉換成Reader對象InputStreamReader reader = new InputStreamReader(System.in);// 將普通Reader包裝成BufferedReaderBufferedReader br = new BufferedReader(reader)){String line = null;// 采用循環方式來一行一行的讀取while ((line = br.readLine()) != null){// 如果讀取的字符串為"exit",程序退出if (line.equals("exit")){System.exit(1);}// 打印讀取的內容System.out.println("輸入內容為:" + line);}}catch (IOException ioe){ioe.printStackTrace();}}15.4.4 推回輸入流
PushbackInputStream和PushbackReader
用unread方法將內容推回到緩沖區,從而允許重復讀取剛剛讀取的內容.
使用推回流,輸出某分割符號之前的內容。但其實完全不必這么做,讀出來判斷就好了。
public static void pushbackTest() {try(// 創建一個PushbackReader對象,指定推回緩沖區的長度為64PushbackReader pr = new PushbackReader(new FileReader("a.txt") , 64)){char[] buf = new char[32];// 用以保存上次讀取的字符串內容String lastContent = "";int hasRead = 0;// 循環讀取文件內容while ((hasRead = pr.read(buf)) > 0){// 將讀取的內容轉換成字符串String content = new String(buf , 0 , hasRead);int targetIndex = 0;// 將上次讀取的字符串和本次讀取的字符串拼起來,// 查看是否包含目標字符串, 如果包含目標字符串if ((targetIndex = (lastContent + content).indexOf("測試")) > 0){// 將本次內容和上次內容一起推回緩沖區pr.unread((lastContent + content).toCharArray());// 重新定義一個長度為targetIndex的char數組if(targetIndex > 32){buf = new char[targetIndex];}// 再次讀取指定長度的內容(就是目標字符串之前的內容)pr.read(buf , 0 , targetIndex);// 打印讀取的內容System.out.print(new String(buf , 0 ,targetIndex));System.exit(0);}else{// 打印上次讀取的內容System.out.print(lastContent);// 將本次內容設為上次讀取的內容lastContent = content;}}}catch (IOException ioe){ioe.printStackTrace();}}system類里提供了三個重定向標準輸入輸出的方法。
setErr(PrintStream err)
setIn(InputStream in)
setOut(PrintStream out)
程序可通過重定向標準輸出流,將System.out的輸出重定向到文件輸出.
15.6 Java虛擬機讀寫其他進程的數據
使用Runtime對象的exec()方法可以運行平臺上的其他程序,該方法產生一個Process對象,Process對象代表由該Java程序啟動的子進程.Process類提供了如下三個方法,用于讓程序和其子進程進行通信.
InputStream getErrorStream():獲取子進程的錯誤流,
InputStream getInputStream(): 獲取子進程的輸入流.
OutputStream getOutputStream(): 獲取子進程的輸出流.
這里的輸入流和輸出流是相對于該java程序(注意,不是子程序)而言的.這里的子進程相當于物理節點
注意,這里用的是getErrorStream(),因為這不是子進程向本進程傳遞的數據,所以屬于其他,要用ErrorStream
public static void readFromProcess() throws IOException {// 運行javac命令,返回運行該命令的子進程Process p = Runtime.getRuntime().exec("java -version");try(// 以p進程的錯誤流創建BufferedReader對象// 這個錯誤流對本程序是輸入流,對p進程則是輸出流BufferedReader br = new BufferedReader(newInputStreamReader(p.getErrorStream()))){String buff = null;// 采取循環方式來讀取p進程的錯誤輸出while((buff = br.readLine()) != null){System.out.println(buff);}}} java version "1.8.0_51" Java(TM) SE Runtime Environment (build 1.8.0_51-b16) Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)?
java兩個程序之間傳遞信息:這端代碼我沒跑起來,待研究
public class WriteToProcess {public static void main(String[] args)throws IOException{// 運行java ReadStandard命令,返回運行該命令的子進程Process p = Runtime.getRuntime().exec("java ReadStandard");try(// 以p進程的輸出流創建PrintStream對象// 這個輸出流對本程序是輸出流,對p進程則是輸入流PrintStream ps = new PrintStream(p.getOutputStream())){// 向ReadStandard程序寫入內容,這些內容將被ReadStandard讀取ps.println("普通字符串");ps.println(new WriteToProcess());}} } // 定義一個ReadStandard類,該類可以接受標準輸入, // 并將標準輸入寫入out.txt文件。 class ReadStandard {public static void main(String[] args){try(// 使用System.in創建Scanner對象,用于獲取標準輸入Scanner sc = new Scanner(System.in);PrintStream ps = new PrintStream(new FileOutputStream("out.txt"))){// 增加下面一行將只把回車作為分隔符sc.useDelimiter("\n");// 判斷是否還有下一個輸入項while(sc.hasNext()){// 輸出輸入項ps.println("鍵盤輸入的內容是:" + sc.next());}}catch(IOException ioe){ioe.printStackTrace();}} }?
15.7 RandomAccessFile
RandomAccessFile可以自由訪問文件的任意位置,所以如果只需要訪問文件部分內容,而不是把文件從頭讀到尾,使用RamdomAccessFile將是更好的選擇.但是局限是,它只能讀寫文件,不能讀寫其他IO節點.
getFilePointer():返回文件記錄指針的當前位置
seek(long pos):將文件記錄指針定位到pos位置
?
public static void randomAccessFileTest(){try(RandomAccessFile raf = new RandomAccessFile("newFile.txt" , "r")){// 獲取RandomAccessFile對象文件指針的位置,初始位置是0System.out.println("RandomAccessFile的文件指針的初始位置:"+ raf.getFilePointer());// 移動raf的文件記錄指針的位置raf.seek(30);byte[] bbuf = new byte[1024];// 用于保存實際讀取的字節數int hasRead = 0;// 使用循環來重復“取水”過程while ((hasRead = raf.read(bbuf)) > 0 ){// 取出“竹筒”中水滴(字節),將字節數組轉換成字符串輸入!System.out.print(new String(bbuf , 0 , hasRead ));}}catch (IOException ex){ex.printStackTrace();}}RandomAccessFile 依然不能向文件的指定位置插入內容,如果直接將文件記錄指針移動到中間某位置后開始輸出,則新輸出的內容會覆蓋文件中原有的內容,如果需要向指定位置插入內容,程序需要先把插入點后面的內容讀入緩沖區,等把需要插入的數據寫入文件后,再將緩沖區的內容追加到文件的后面.
?
public static void insert(String fileName , long pos, String insertContent) throws IOException{File tmp = File.createTempFile("tmp" , null);tmp.deleteOnExit();try(RandomAccessFile raf = new RandomAccessFile(fileName , "rw");// 使用臨時文件來保存插入點后的數據FileOutputStream tmpOut = new FileOutputStream(tmp);FileInputStream tmpIn = new FileInputStream(tmp)){raf.seek(pos);// ------下面代碼將插入點后的內容讀入臨時文件中保存------byte[] bbuf = new byte[64];// 用于保存實際讀取的字節數int hasRead = 0;// 使用循環方式讀取插入點后的數據while ((hasRead = raf.read(bbuf)) > 0 ){// 將讀取的數據寫入臨時文件tmpOut.write(bbuf , 0 , hasRead);}// ----------下面代碼插入內容----------// 把文件記錄指針重新定位到pos位置 raf.seek(pos);// 追加需要插入的內容 raf.write(insertContent.getBytes());// 追加臨時文件中的內容while ((hasRead = tmpIn.read(bbuf)) > 0 ){raf.write(bbuf , 0 , hasRead);}}}如果僅僅是追加內容,就簡單多了
public static void main(String[] args){try(//以讀、寫方式打開一個RandomAccessFile對象RandomAccessFile raf = new RandomAccessFile("out.txt" , "rw")){//將記錄指針移動到out.txt文件的最后 raf.seek(raf.length());raf.write("追加的內容!\r\n".getBytes());}catch (IOException ex){ex.printStackTrace();}}?
15.8 對象序列化(serialize)
對象的序列化指將一個java對象寫入IO流中,與此對應的是,對象的反序列化(Deserialize)則指從IO流中恢復該java對象.
如果需要讓某個對象支持序列化機制,那么必須讓它的類是可序列化的,必須實現如下兩個接口之一
Serializable
Externalizable
程序創建的每個JavaBean類都要實現Serializable
public static void writeObject() {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));) {LearnIO learnIO = new LearnIO("12334444444");oos.writeObject(learnIO);} catch (IOException ex) {// TODO: handle exception ex.printStackTrace();}}//但是,如果如下
LearnIO learnIO = new LearnIO("12334444444");
oos.writeObject(learnIO);
learnIO.test="abcdetc";
//不會寫入abcdetc,因為不會序列化號碼相同的東西oos.writeObject(learnIO);
反序列化
public static void readObject(){try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));){LearnIO learnIO = (LearnIO)ois.readObject();System.out.println(learnIO.test);}catch (Exception e) {// TODO: handle exception e.printStackTrace();}}反序列化機制無須通過構造器來初始化java對象.
如果使用序列化機制向文件中寫入多個Java對象,使用反序列化機制恢復對象時必須按實際寫入的順序讀取.
當一個可序列化類有多個父類時(包括直接父類和間接父類),這些父類要么有無參數的構造器,要么也是可序列化的--否則反序列化時將拋出InvalidClassException異常.如果父類是不可序列化的,只是帶有無參數的構造器,則該父類中定義的成員變量值不會序列化到二進制流中.
?
15.8.3 對象引用的序列化
如果成員變量是引用類型,那么這個引用類型的類必須是可序列化的.
屬于遞歸序列化
有static修飾和transient修飾的變量不會被序列化
15.8.4 自定義序列化
在實例變量前面使用transient關鍵字修飾,可以指定java序列化時無須理會該實例變量.
更詳細的自定義序列化方法是重寫writeObject和readObject方法.
?
15.8.5 另一種自定義序列化機制
實現Externalizable
?
轉載于:https://www.cnblogs.com/lakeslove/p/6143568.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java8--IO(java疯狂讲义3复习笔记)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: autoitv3点击windows界面
- 下一篇: NAT协议详解