日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java】15 输入输出

發布時間:2025/3/20 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】15 输入输出 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 一、File類
        • 1.訪問文件和目錄
        • 2.文件過濾器
      • 二、理解Java的IO流
        • 1.流的分類
          • ①按數據流向分類
          • ②按數據單元的長度劃分
          • ③按流的角色來分類
        • 2.流的概念模型
      • 三、字節流和字符流
        • 1.輸入流中的字節流和字符流
        • 2.輸入流中的字節流和字符流
      • 四、輸出/輸出流體系
        • 1.處理流用法
        • 2.輸入/輸出流體系
        • 3.轉換流
        • 4.推回輸入流
      • 五、重定向標準輸入輸出
      • 六、Java虛擬機讀寫其他進程的數據
      • 七、RandomAccessFile
      • 八、對象序列化
        • 1.序列化的含義和意義
        • 2.使用對象流實現序列化
          • 序列化
          • 反序列化
        • 3.對象引用的序列化
        • 4.自定義序列化
      • 九、NIO
        • 1.Buffer
        • 2.Channel

一、File類

1.訪問文件和目錄

/** * @ClassName: FileTest* @description: 本節代碼主要討論FIle類的相關訪問文件和目錄* @author: FFIDEAL* @Date: 2020年4月10日 上午10:17:48*/ package M15;import java.io.File; import java.io.IOException;public class FileTest {public static void main(String[] args) throws IOException{//以當前===路徑===來創建一個File對象File file = new File(".");//獲取文件名System.out.println(file.getName()); //輸出:newFile.txt//獲取相對路徑的父路徑(可能會出錯,輸出null)System.out.println(file.getParent());//獲取絕對路徑 System.out.println(file.getAbsolutePath()); //輸出:E:\JavaCode\Code\newFile.txt//獲取上一級路徑System.out.println(file.getAbsoluteFile().getParent()); //輸出:E:\JavaCode\Code//在當前路徑下創建一個臨時文件File tmpFile = File.createTempFile("tempFile", ".txt");//輸出當前臨時文件的絕對路徑System.out.println(tmpFile.getParent()); //指定JVM退出時刪除該文件tmpFile.deleteOnExit();//以系統當前時間來命令新文件File newFile = new File(System.currentTimeMillis()+"");System.out.println("newFile對象是否存在:" + newFile.exists());newFile.createNewFile();//以newFile創建一個目錄,因為newFile已經存在//所以下面方法返回false,即無法創建該目錄newFile.mkdir();//使用list()方法列出當前路徑下的所有文件String[] fileList = file.list(); System.out.println("===當前路徑下的所有文件和路徑==="); for(String fileName : fileList){System.out.println(fileName);}//listRoots()靜態方法列出所有磁盤根路徑File[] roots = File.listRoots();System.out.println("===系統過有根目錄===");for(File root : roots) {System.out.println(root);}//listFiles是獲取該目錄下所有文件和目錄的絕對路徑 File[] fs = file.listFiles();for(File f:fs) {System.out.println(f);}} }

2.文件過濾器

/** * @ClassName: FileNameFilterTest* @description: 文件過濾器* @author: FFIDEAL* @Date: 2020年4月14日 上午10:07:43*/ package M15;import java.io.File;public class FileNameFilterTest {public static void main(String[] args) {File file = new File(".");//文件以“.java”結尾或者文件對應一個路徑,則返回trueString[] nameList = file.list((dir , name) -> name.endsWith(".java") || new File(name).isDirectory());for(int i = 0; i < nameList.length; i++) {System.out.println(i);System.out.println(nameList[i]);}for(String name : nameList) {System.out.println(name);}} }

二、理解Java的IO流

1.流的分類

①按數據流向分類

? 從程序所在內存角度劃分

? 輸出流:只能向其寫入數據,而不能從中讀取數據(內存 → 硬盤)------- 基類為:OutputStream類和Writer類

? 輸入流:只能從中讀取數據,而不能向其寫入數據(cache → 內存)--------基類為:InputStream類和Reader類

②按數據單元的長度劃分

? 字節流:數據單元為8位的字節 ------- 基類為:InputStream類和OutputStream類

? 字符流:數據單元為16位的字節------- 基類為:Writer類和Reader類

③按流的角色來分類

? 節點流:從特定的IO設備(如磁盤、網絡等)讀/寫的數據的流

? 處理流:用一個已存在的流進行連接或封裝,通過封裝后的流來實現讀/寫的數據的功能

? 處理流的好處:不能直接連接到實際的數據源,可以采用完全相同的輸入/輸出代碼來訪問不同的數據源,消除不同節點流帶來的差異(只要使用相同的處理流)————變壓器?

2.流的概念模型

? Reader/Writer:是對人來說,Reader讀者,獲取知識,輸入;Writer寫著,輸出知識,輸出

? InputStream/Reader:所有輸入流的基類,前者是字節輸入流,后者是字符輸入流

? OutputStream/Writer:所有輸出流的基類,前者是字節輸出流,后者是字符輸出流

三、字節流和字符流

1.輸入流中的字節流和字符流

read():讀取一個“水滴(字節或字符)”

read(byte[] b)/read(char[] ch):讀取多個"水滴"

read(char[] ch,int off,int len)/read(byte[] ch,int off,int len):同上,規定了長度

字節流

/** * @ClassName: FileInputStreamTest* @description: 本節代碼討論了使用FileInputStream (字節流而非字符流)輸入流讀取數據的一種實現方法* 注意:在本節代碼中,如果設置的“水管”不長,也就是說,不能一次性取完文件中所有的數據,要分多批次* 此時,若文件中時有中文的話,意味著可能會發生亂碼 ———— 原因是,中文占2個字符,而讀取時,只能制度去一個字符* @author: FFIDEAL* @Date: 2020年4月14日 下午2:06:07*/ package M15;import java.io.FileInputStream; import java.io.IOException;public class FileInputStreamTest {public static void main(String[] args) throws IOException{//創建一個字節輸入流FileInputStream fis = new FileInputStream("E:\\JavaCode\\Code\\src\\M15\\FileNameFilterTest.java");//創建一個字節流水管,用來取水byte[] bbuf = new byte[1024];//用于保存實際讀取的字節數int hasRead = 0;//當水管里還有水的時候while((hasRead = fis.read(bbuf)) > 0) {System.out.println(new String(bbuf , 0 , hasRead));}//關閉水管fis.close();} }

字符流

/** * @ClassName: FileInputStreamTryCatchTest* @description: 本節代碼主要討論使用try-catch和FileReader(字符輸入流) 字符流 來實現輸入流的實現過程* 另外,也是使用了自動關閉資源的try語句來關閉文件輸入流* @author: FFIDEAL* @Date: 2020年4月14日 下午2:18:59*/ package M15;import java.io.FileReader; import java.io.IOException;public class FileInputStreamTryCatchTest {public static void main(String[] args) throws IOException{try(FileReader fis = new FileReader("E:\\JavaCode\\Code\\src\\M15\\FileNameFilterTest.java")){//創建一個字符流水管char[] chbuf = new char[32];//取水珠計數器int hasRead = 0;while((hasRead = fis.read(chbuf)) > 0) {System.out.println(new String(chbuf, 0 , hasRead));}}catch(IOException ex) {ex.printStackTrace();}} }

2.輸入流中的字節流和字符流

write(int a):寫入一個字節/字符

write(byte[] b/char[] ch):寫入一組數據

write(byte[] b/char[] ch,int off,int len):寫入一組由off開始,長度為lend數據

字節流

/** * @ClassName: FileOutputStreamTest* @description: 本節代碼主要討論==字節輸出流==的實現類,配合字節輸入流,將一個文檔里面的數據轉移到另一個文檔中去* @author: FFIDEAL* @Date: 2020年4月14日 下午2:32:35*/ package M15;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;public class FileOutputStreamTest {public static void main(String[] args) throws IOException{try(//創建一個字節輸入流FileInputStream fis = new FileInputStream("E:\\JavaCode\\Code\\src\\M15\\FileNameFilterTest.java");//創建一個字節輸出流FileOutputStream fos =new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\FileNameFilterTest.txt")){//創建一根字節流水管byte[] bbuf = new byte[1024];//取水計數器int hasRead = 0;while((hasRead = fis.read(bbuf)) > 0) {//每讀一次,即寫入文件輸出流,讀了多少就寫多少fos.write(bbuf, 0, hasRead);}}catch(IOException ex) {ex.printStackTrace();}} }

字符流

/** * @ClassName: FileWriterTest* @description: 本節討論了使用==字符輸出流==來實現將一首詩寫入到文件中,同時也將一個文件里的數據寫入到另一個文件里* @author: FFIDEAL* @Date: 2020年4月14日 下午2:41:50*/ public class FileWriterTest {public static void main(String[] args) throws IOException {try(//創建一個字符輸出流FileWriter fw = new FileWriter("E:\\JavaCode\\Code\\src\\M15\\pom.txt");){fw.write("床前明月光,\t\n");fw.write("疑是地上霜。\t\n");fw.write("舉頭望明月。\t\n");fw.write("低頭思故鄉。\t\n");}catch(IOException ex) {ex.printStackTrace();}//創建一個字符輸入流FileReader fr = new FileReader("E:\\JavaCode\\Code\\src\\M15\\pom.txt");//創建一個字符輸出流FileWriter fw = new FileWriter("E:\\JavaCode\\Code\\src\\M15\\pomWriter.txt");//創建一根水管char[] chbuf = new char[1024];//取水計數器int hasRead = 0;while((hasRead = fr.read(chbuf)) > 0) {fw.write(chbuf, 0, hasRead);}//關閉輸入流和輸出流fr.close();fw.close();} }

四、輸出/輸出流體系

1.處理流用法

處理流的典型思路是:使用處理流來包裝節點流,程序通過處理流來執行輸入、輸出功能,讓節點流和底層IO設備以及文件交互

識別處理流很簡單:只要流的構造器參數不是一個物理節點,而是已經存在的流,那么這種流就是處理流

/** * @ClassName: PrintStreamTest* @description: 本節代碼討論的是PrintStream處理流,* @author: FFIDEAL* @Date: 2020年4月15日 下午1:46:30*/ public class PrintStreamTest {public static void main(String[] args) throws IOException{try(//創建一個字節流FileOutputStream fos = new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\print.txt");//創建一個PrintStream流,把FileOutputStream字節流包裝起來PrintStream ps = new PrintStream(fos)){//使用PrintStream執行輸出ps.println("PrintStream執行輸出");//直接使用PrintStream對象輸出對象ps.println(new PrintStreamTest());}catch(IOException e) {e.printStackTrace();}} }

2.輸入/輸出流體系

字節流以字節數粗為節點,字符流以字符數組為節點;

字符流可以使用字符串作為物理節點,用于實現從字符串讀取內容,或將內容寫入字符串

/** * @ClassName: StringNodeTest* @description: 本節代碼主要討論輸入輸出的體系問題* @author: FFIDEAL* @Date: 2020年4月15日 下午2:09:39*/ public class StringNodeTest {public static void main(String[] args) throws IOException{String src ="一去二三里,煙村四五家。 \r\n" + "亭臺六七座,八九十枝花。";char[] chbuf = new char[1024];int hasRead = 0;try(StringReader sr = new StringReader(src)){//以循環的方式讀取字符串while((hasRead = sr.read(chbuf)) > 0) {System.out.println(new String(chbuf,0,hasRead));}}catch(IOException ioe) {ioe.printStackTrace();}try(//創建StringWriter時,是加上以一個StringBuffer作為輸出節點//一面指定的20就是StringBuffer的初始長度StringWriter sw = new StringWriter()){sw.write(src);System.out.println("===下面是sw字符串節點里面的內容===");System.out.println(sw.toString());}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

3.轉換流

/** * @ClassName: KeyinTest* @description: 本節代碼主要討論System.in對象轉換成Reader對象(利于包裝為BufferReader),* 將普通的Reader包裝為BufferReader(使用BufferReader對象的方法利于讀取)* @author: FFIDEAL* @Date: 2020年4月15日 下午4:29:34*/ package M15;public class KeyinTest {public static void main(String[] args) throws IOException{try(//將System.in對象轉換成Reader對象InputStreamReader isr = new InputStreamReader(System.in);//將普通的Reader包裝為BufferReaderBufferedReader br = new BufferedReader(isr)){String line =null;//采用循環的方式來讀取while((line = br.readLine()) != null) {//如果讀取到字符串“exit”,程序就退出if(line.equals("exit")) {System.exit(1);}System.out.println("輸出內容為:" + line);}}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

4.推回輸入流

就是輸出到—傳入的參數----輸出傳參以前的字符

五、重定向標準輸入輸出

將System.out的輸出重定向到指定文件輸出,而非在屏幕上輸出

/** * @ClassName: RedirectOut* @description: 本節代碼主要討論將系統的標準輸出重定向到該printStream輸出流* 運行上面程序時將看不到任何輸出 ———— 這意味著標準輸出不再輸出到屏幕,而是輸出到out.txt* 將System.in重定義到指定文件里的內容,正好與程序中的輸出一致* @author: FFIDEAL* @Date: 2020年4月15日 下午6:05:58*/ public class RedirectOut {public static void main(String[] args) throws IOException{try(//一次性創建PrintStream輸出流PrintStream ps = new PrintStream(new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\out.txt"))){//將標準輸出重定向到ps輸出流System.setOut(ps);//向標準輸出輸出一個字符串System.out.println("這是一個字符串");//向標準輸出輸出一個對象System.out.println(new RedirectOut());}catch(IOException ioe) {ioe.printStackTrace();}} }

將System.in的重定向到指定文件,而不是鍵盤輸入

/** * @ClassName: RedirectIn* @description: 創建一個FileInputStream輸入流,并使用System的setIn()方法將系統標準輸入重定向到該文件輸入流* 運行本程序,程序不會等用戶輸入,而是直接輸出RedirectOut.java文件的內容,這表明程序不再使用鍵盤作為標準輸入* @author: FFIDEAL* @Date: 2020年4月15日 下午9:42:45*/ public class RedirectIn {public static void main(String[] args) throws IOException{try(//創建一個FileInputStream輸入流FileInputStream fis = new FileInputStream("E:\\JavaCode\\Code\\src\\M15\\RedirectOut.java")){//將標準輸入重定向到fis輸出流System.setIn(fis);//使用System.in創建Scanner對象,用于獲取標準輸入Scanner sc = new Scanner(System.in);//增加下面一行只把回車作為分隔符sc.useDelimiter("\n");//判斷是否還有下一個輸入項while(sc.hasNext()) {System.out.println("鍵盤輸入的內容是:" + sc.next());}}catch(IOException ioe) {ioe.printStackTrace();}} }

六、Java虛擬機讀寫其他進程的數據

/** * @ClassName: ReadFromProcess* @description: 本節代碼主要討論使用Runtime對象的exec()方法可以運行平臺上的其他程序,* 該方法產生一個Process對象,* Process對象代表由該Java程序啟動的子進程* @author: FFIDEAL* @Date: 2020年4月16日 上午10:50:18*/ public class ReadFromProcess {public static void main(String[] args) throws IOException{//運行javac命令,返回運行該命令的子進程Process p = Runtime.getRuntime().exec("javac");try(//以p進程的錯誤流創建BufferReader對象,這個錯誤流對本程序是輸入流,對p進程是輸出流BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()))){String buff = null;while((buff = br.readLine()) != null) {System.out.println(buff);}} } } /** * @ClassName: WriteToProcess* @description: 本節代碼討論通過Process的getOutStream()方法獲得向進程輸入數據的流,* 如下程序實現了在java程序中啟動Java虛擬機運行另一個java程序,并向另一個程序輸入數據* @author: FFIDEAL* @Date: 2020年4月16日 下午12:50:20*/ public class WriteToProcess {public static void main(String[] args) throws IOException{//運行Java ReadStandard命令,返回該命令的子進程Process p = Runtime.getRuntime().exec("Java ReadStandard");try(//以p進程的輸出流創建PrintStream對象//對于程序來說這是輸出流,對于子進程來說,這是輸入流PrintStream ps = new PrintStream(p.getOutputStream());){//向ReadStandard程序寫入內容,這些內容被ReadStandard讀取ps.println("這是ReadStandard讀取的內容");ps.println(new WriteToProcess()); }} }//定義一個ReadStandard類,該類可以接收標準輸入 //并將標準輸入寫入ReadStandard.txt文件中d class ReadStandard{public static void main(String[] args) throws IOException{try(//使用System.in創建Scanner對象用于標準輸入Scanner sc = new Scanner(System.in);PrintStream ps = new PrintStream("E:\\JavaCode\\Code\\src\\M15\\ReadStandard.txt")){//增加下面一行只把回車作為分隔符sc.useDelimiter("\n");while(sc.hasNext()) {//輸出鍵盤輸入的內容System.out.println("鍵盤輸入的內容是:" + sc.next());}}catch(Exception e) {e.printStackTrace();}} }

七、RandomAccessFile

RandomAccessFile(任意訪問文件):是功能最豐富的文件訪問類,它既==可以讀文件,也可以寫文件,同時還有**“任意訪問”==**文件。若只需要訪問文件的部分內容,而非把文件從頭到尾讀取,采用RandomAccessFile類將是一個很好的選擇。

但是她有一個缺陷,也就是說他只能讀寫文件但**不能讀寫其他IO節點**。

以下使用RandomAccessFile來訪問指定的中間部分數據

public class RandomAccessFiletest {public static void main(String[] args) throws IOException{try(//創建一個RandomAccessFile對象RandomAccessFile raf = new RandomAccessFile("E:\\JavaCode\\Code\\src\\M15\\pomWriter.txt", "r");){//獲取RandomAccessFile對象指針位置,初始位置為0System.out.println("RandomAccessFile的文件指針的初始地址" + raf.getFilePointer());//移動文件記錄指針位置raf.seek(6);byte[] bbuf = new byte[1024];//記錄實際讀取的字節數int hasRead = 0;while((hasRead = raf.read(bbuf)) > 0) {//取出竹筒中的水滴(“字節”),將字節數組轉換成字符串輸入System.out.println(new String(bbuf,0,hasRead));}}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

下面代碼是寫入文件

public class AppendContent {public static void main(String[] args) throws IOException{try(//以“讀寫”的方式打開一個RandomAccessFile對象RandomAccessFile raf = new RandomAccessFile("E:\\JavaCode\\Code\\src\\M15\\pomWriter.txt", "rw");){//將指針移動到最后raf.seek(raf.length());raf.write("\n這是使用RandomAccessFile對象追加的內容".getBytes());}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

下面程序實現了向指定文件、指定位置插入內容的功能

/** * @ClassName: InsertContent* @description: 本節代碼向指定位置插入數據,在此位置之后的數據放入緩存區,* 當全部寫完輸入后,緩存區里的數據接在插入數據之后* @author: FFIDEAL* @Date: 2020年4月16日 下午5:42:01*/ public class InsertContent {public static void insert(String fileName, long position , 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(position);//下面代碼將插入點后的內容讀入臨時文件中保存byte[] bbuf = new byte[20];//用于保存實際讀取的字節int hasRead = 0;while((hasRead = raf.read(bbuf)) > 0) {//將讀取的數據寫入 臨時文件tmpOut.write(bbuf, 0, hasRead);}//下面代碼用于插入內容//把文件記錄指針重新定位到pos位置raf.seek(position);//追加需要插入的內容raf.write(insertContent.getBytes());//追加臨時文件中的內容while((hasRead = tmpIn.read(bbuf)) > 0) {raf.write(bbuf,0,hasRead);}}}public static void main(String[] args) throws IOException {insert("E:\\JavaCode\\Code\\src\\M15\\print.txt", 45, "=========================");} }

八、對象序列化

1.序列化的含義和意義

序列化機制:將實現序列化的Java對象轉換成字節序列,這些字節序列可以保存在磁盤上,或通過網絡傳輸,以備以后重新恢復成原來的對象 —— 序列化機制使得對象可以脫離程序存在

對象的序列化:講一個Java對象希爾IO流中,與此對應的四,對象的反序列化則指從IO流中恢復該Java對象

實現對象的序列化的前提就是對象的類要序列化,類的序列化就是必須實現Serialiable或Externalizable接口

2.使用對象流實現序列化

使用Serializable來實現序列化非常簡單,主要讓目標實現Serializable標記接口即可,無需事先任何方法

? 1.創建ObjectOutputStream,這是一個輸出流

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));

? 2.調用ObjectOutputStream對象的writeObject()方法輸出可序列化對象

oos.writeObject(per);
序列化

實例代碼

//創建一個普通類,繼承Serializable接口。當然Externalizable接口也行 public class Person implements Serializable{private String name;private int age;public Person(String name, int age) {System.out.println("有參數構造器");this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

使用objectOutputStream(對象輸出流)講一個Person類的對象寫入文件中

public class WriteObject {public static void main(String[] args) throws IOException{try(//創建一個ObjectoutputStream輸出流ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\Seriliable.txt"));){Person per = new Person("張三", 18);//將這個對象寫入輸出流oos.writeObject(per);}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }
反序列化

1.創建一個ObjectInputStream輸入流,這個輸入流是一個處理流,必須建立在其他節點流基之上

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));

2.調用ObjectInputStream對象的readObject()方法讀取流中的對象,該方法返回一個Object類型的java對象

Person p = (Person)ois.readObject();

以下代碼示范了剛剛生成的文件中讀取Person對象的步驟

public class ReadObjectTest {public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\JavaCode\\Code\\src\\M15\\Seriliable.txt"))){Person p = (Person)ois.readObject();System.out.println("p的姓名:" + p.getName() + ",年齡:" + p.getAge());}catch(Exception e) {e.printStackTrace();}} }

注意:反序列化讀取的僅僅使Java對象的數據,而非Java類

若使用序列化機制向文件中寫入多個Java對象,使用反序列化機制恢復對象時必須按實際寫入的順序讀取

3.對象引用的序列化

若一個類的成員變量不是基本類型或者String型,而是另一種引用類型,那么這個引用類必須是可序列化的

此外,序列化機制會采用一種特殊的序列化算法

1.所有保存到磁盤中的對象都有一個序列化編號

2.在程序試圖序列化一個對象的時候,程序會優先檢查該對象是否被序列化過,若沒有,系統才會將該對象轉換成字節序列并輸出

3.程序將只是直接輸出一個序列化編號,而不是再次重新序列化該對象

public class Teacher implements Serializable{private String name;private Person student;public Teacher(String name,Person student) {this.name = name;this.student = student;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Person getStudent() {return student;}public void setStudent(Person student) {this.student = student;} } public class WriteTeacher {public static void main(String[] args) throws FileNotFoundException, IOException {try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\teacher.txt"))){Person per = new Person("小明", 13);Teacher t1 = new Teacher("王老師", per);Teacher t2 = new Teacher("張老師", per);//依次將4個對象寫入輸出流oos.writeObject(t1);oos.writeObject(t2);oos.writeObject(per);oos.writeObject(t2);}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

上面writeObject()方法仿佛寫入了四個對象,但實際上只寫入三個對象,而且序列的兩個Teacher對象的student引用實際是同一個Person對象。下面程序讀取序列化文件中的對象即可證明

public class ReadTeacher {public static void main(String[] args) throws FileNotFoundException,IOException, ClassNotFoundException{try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\JavaCode\\Code\\src\\M15\\teacher.txt"))){//依次讀取ObjectInputStream輸入流中的4個對象Teacher t1 = (Teacher)ois.readObject();Teacher t2 = (Teacher)ois.readObject();Person per = (Person)ois.readObject();Teacher t3 = (Teacher)ois.readObject();//輸出trueSystem.out.println("t1的student引用和p是否相同:" + (t1.getStudent()==per));//輸出trueSystem.out.println("t2的student引用和p是否相同:" + (t2.getStudent()==per));//輸出trueSystem.out.println("t2和t3是否相同:" + (t2==t3));}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

注意:序列化機制當程序序列化一個可變對象時,只有第一次使用writeObject()方法輸出時才會將該對象轉換成字節序列并輸出,再次調用只會輸出前面序列化的編號

4.自定義序列化

在一些特殊的場景下不希望系統將實例變量值進行序列化

通過在實例變量前用transient關鍵詞修飾,可以指定Java序列化無需理會該實例變量。

private transient int age;

下面程序先序列化一個Person對象,然后再反序列化該Person對象,得到反序列化兌現的Person對象之后程序輸出該對象的age實例變量值

public class TransientTest {public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\transient.txt"));ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\JavaCode\\Code\\src\\M15\\transient.txt"))){Person per = new Person("哪吒", 7);oos.writeObject(per);Person p = (Person)ois.readObject();System.out.println(p.getAge());}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

九、NIO

新IO采用內存映射文件的方式來處理輸入/輸出,新IO將文件或文件的一段區域映射到內存中,這樣就可以像訪問內存一樣來訪問文件。Channel(通道)和Buffer(緩沖)是新IO的兩個核心對象。

Channel比InputStream、OutputStream最大的區別在于他提供了一個map方法,通過這個方法可以直接將“一塊數據”映射到內存中。Buffer可以被理解成一個容器,它的本質是一個數組,發送到Channel中的所有對象都必須首先放到Buffer中去。

打個比方:Buffer既可以像“竹筒”一樣一次次從Channel中取水,也允許使用Channel直接將文件袋某塊數據映射成Buffer

1.Buffer

Buffer有三個重要的概念:容量(capacity)、界限(limit)和位置(position)

/** * @ClassName: BufferTest* @description: * @author: FFIDEAL* @Date: 2020年4月17日 下午9:44:47*/ package M15;import java.nio.CharBuffer;public class BufferTest {public static void main(String[] args) {//創建Buffer,通過CharBuffer的一個靜態方法allocate創建一個capacity為8的CharBufferCharBuffer buff = CharBuffer.allocate(8);System.out.println("capacity:" + buff.capacity()); //輸出:capacity:8System.out.println("limit:" + buff.limit()); //輸出:limit:8System.out.println("position:" + buff.position()); //輸出:position:0//放入元素buff.put('a');buff.put('d');buff.put('e');System.out.println("加入三個元素之后:position:" + buff.position()); //輸出:加入三個元素之后:position:3//調用flip(),把limit設為position處,把position設為0buff.flip();System.out.println("執行flip()方法之后,limit = "+ buff.limit()); //輸出:執行flip()方法之后,limit = 3System.out.println("執行flip()方法之后,position = "+ buff.position()); //輸出:執行flip()方法之后,limit = 3//取出第一個元素System.out.println("第一個元素position = 0:" + buff.get()); //輸出:第一個元素position = 0:aSystem.out.println("取出一個元素后的position = " + buff.position()); //輸出:取出一個元素后的position = 1//調用clear方法,將position歸0,limit = capacitySystem.out.println("執行clear()方法之后,limit = " + buff.limit()); //輸出:執行clear()方法之后,limit = 3System.out.println("執行clear()方法之后,position = " + buff.position()); //輸出:執行clear()方法之后,position = 1System.out.println("執行clear()后,緩沖區內容并沒有被清除,第三個元素為"+ buff.get(2)); //輸出:執行clear()后,緩沖區內容并沒有被清除,第三個元素為eSystem.out.println("執行絕對讀取后,position = " + buff.position()); //輸出:執行絕對讀取后,position = 1} }

2.Channel

Channel有以下兩個特點

  • Channel可以直接將指定的文件部分或全部映射成Buffer
  • 程序不能直接訪問Channel,讀寫都不行,Channel只能與Buffer交互
  • Channel有三個主要的方法:map() read() write()

    public class FileChannelTest {public static void main(String[] args) throws FileNotFoundException, IOException {File f = new File("E:\\JavaCode\\Code\\src\\M15\\print.txt");try(//創建FileInputStream,以文件輸入流創建FileChannelFileChannel inChannel = new FileInputStream(f).getChannel();//文件輸出流創建FileChannel,用以控制輸出FileChannel outChannel = new FileOutputStream("E:\\JavaCode\\Code\\src\\M15\\ChannelOut.txt").getChannel();){//將FileChannel里的全部數據映射成ByteBuffer,將FileChannel里面的輸出全部改為ByteChannelMappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());//使用GBK的字符集來創建解碼器Charset charset = Charset.forName("GBK");//直接將buffer里的數據全部輸出,將整個ByteBuffer的全部數據寫入一個輸出FileChanneloutChannel.write(buffer);//在調用buffer的clear()方法,復原limit和position的位置buffer.clear();//創建解碼器(CharsetDecoder)對象CharsetDecoder cd = charset.newDecoder();//使用解碼器將ByteBuffer轉換成charBufferCharBuffer cb = cd.decode(buffer);//CharBuffer的toString方法可以獲取對應的字符串System.out.println(cb);}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} }

    總結

    以上是生活随笔為你收集整理的【Java】15 输入输出的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 久久这里有精品 | 性大片潘金莲裸体 | 久久人人爽人人爽 | 国产精品国产三级国产播12软件 | 精品一区二区成人免费视频 | 久久中文在线 | 狠狠爱欧美 | 国产免费成人 | 免费一级欧美片在线播放 | 成人在线免费网站 | 亚洲国产剧情在线观看 | 亚洲午夜网站 | 国产三区视频 | av无码一区二区三区 | 中文在线一区 | 久久77| 丰满熟妇肥白一区二区在线 | 亚洲国产一区二区三区a毛片 | 天天干天天日 | 在线视频 中文字幕 | av丝袜在线 | 福利视频导航网 | 日本在线观看网站 | 操操操免费视频 | 欧美丰满熟妇bbb久久久 | 亚洲一区二区三区四区在线观看 | 久久国产精品-国产精品 | 中文字幕免费一区 | 少妇无码一区二区三区免费 | 日产精品一区二区 | 国产不卡免费视频 | 韩国裸体网站 | 国产亚韩 | wwwav在线播放 | 国产另类av | 99久久一区 | 97小视频| 51吃瓜网今日吃瓜 | 不卡视频一区二区三区 | 亚洲色图国产精品 | h在线网站 | 国产福利av| 四虎视频国产精品免费 | 视频免费1区二区三区 | 久久午夜精品视频 | 黄色一级片在线看 | 一级做a爰片久久毛片 | 无码任你躁久久久久久老妇 | 别揉我奶头一区二区三区 | 日韩成人看片 | 久久精品h | 国产精品久久一区二区三区动 | 影音先锋在线视频 | 亚洲精品第三页 | 国产最新毛片 | 日本一区二区在线 | 伊人影院在线视频 | 婷婷六月综合网 | 国产污视频在线播放 | 麻豆免费观看视频 | 一级片免费视频 | 伊人影院在线观看视频 | av激情在线观看 | 天堂网亚洲 | 中文字幕一区二区三区人妻四季 | 国产.com| 日韩精品人妻无码一本 | 97精品国产97久久久久久粉红 | 亚洲精品在线免费播放 | 久久伊人色 | 亚洲国产精品久久久 | av精选 | 红桃视频国产 | 成人免费看片网站 | 国产午夜伦理 | 美女搡bbb又爽又猛又黄www | 韩国精品久久久 | 高清国产一区二区三区四区五区 | 日韩爱爱片 | 国产精品久久久免费视频 | 可以直接看的无码av | 色网导航站 | 一二三四视频社区在线 | 日韩成人综合网 | 天天干夜夜撸 | 国产欧美日韩精品一区 | 亚洲天堂aaa | 中文字幕在线观看二区 | 日韩一二三区 | 蜜桃视频欧美 | 丰满少妇一区二区三区专区 | 欧美人禽杂交狂配 | 草草屁屁影院 | 中文字幕色哟哟 | 天堂一区在线 | 亚洲熟女一区二区三区 | 黄色网www | 日韩国产在线播放 | 欧美天天干|