Java 输入输出流学习总结
文章目錄
- 前言:為什么要有輸入輸出流
- 一、Java 的標準輸入輸出
- 標準輸入 System.in
- 標準輸出 System.out
- 程序 exp8_3:簡單的輸入輸出
- 二、輸入輸出流框架
- 三、輸入輸出流類的應用
- 課本程序 exp8.4
- 改寫 exp8.4(1)
- 改寫 exp_8.4(2)
- 四、RandomAccessFile 類
- 輸入輸出流總結
前言:為什么要有輸入輸出流
為什么 Java 要有輸入輸出流?我們先來看看用現有手段寫一個簡單的輸入輸出程序:
package big;import java.util.Scanner;public class Simlpe_input_and_output {public static void main(String[] args) {// TODO 自動生成的方法存根Scanner read = new Scanner (System.in);System.out.println("請輸入你想輸入的內容:");String a = read.next();System.out.println("接下來打印這句話:");System.out.println(a);}}你看看這多麻煩,要想從鍵盤上輸入還得先導入 util 包里的 Scanner 類,在一開始學 Java 的時候差點因為這個導致厭學(C語言直接 scanf、printf 不好嗎?為啥 Java還得三行代碼?) 。
接下來還是看看課本上的介紹吧:Java 語言的輸入輸出功能是十分強大而靈活的(說實話,我現在都不信🥱🥱🥱),對于數據的輸入和輸出操作以 “ 流 ”(stream)的方式進行。JDK 提供了各種各樣的 “ 流 ” 類,用以獲取不同種類的數據,它們都定義在 java.io 包中。程序中通過標準的方法輸入或輸出數據。
嗯~~那下面我們就來看看這 Java 輸入輸出流到底咋回事吧,這里主要還是對課本中的示例代碼進行復現來學習的,所以課本看不懂的小伙伴可以試試我的這篇學習筆記。
一、Java 的標準輸入輸出
標準輸入輸出功能是通過 Java 的 System 系統類來實現的。System 類在 java.lang 包中,是一個最終類,里面的大多數方法都是靜態方法,所以在程序中可以直接調用它們(包括標準輸入輸出)。
什么?不知道 java.lang 是啥?老師上課講過的,language 嘛,語言的縮寫。java.lang包是java語言的核心,它提供了java中的基礎類。包括基本Object類、Class類、String類、基本類型的包裝類、基本的數學類等等最基本的類。也就是說,一個 Java 程序必備 java.lang 包(默認就存在的吧,我也沒見課本示例程序里寫啊,是吧?)
標準輸入 System.in
System.in 作為 InputStream 類的對象實現標準輸入,可以調用它的 read 方法(有以下三種格式)來讀取鍵盤數據:
輸入流結束,返回 -1。
標準輸出 System.out
System.out 作為 PrintStream 打印流類的對象實現標準輸出,可以調用它的 ptint 、println 或 write 方法來輸出各種類型的數據。
print 和 println 都不用介紹了,目前用的最多的代碼就是寫這個的。還是說一下 wtite 方法吧,它用來輸出字節數組,注意一點:write 方法在輸出單個字節時并不能立即顯示出來,還需調用 flush 或 close 方法來強制回調(??不懂)。
程序 exp8_3:簡單的輸入輸出
package big;import java.io.IOException;public class exp8_3_simple_inputoutput {public static void main(String[] args) throws java.io.IOException { //這里必須繼承 IOException 異常,因為輸入時可能會發生 I/O 錯誤byte buffer[] = new byte[40];System.out.println("從鍵盤上輸入不超過40個字符,按回車鍵結束輸入:");int count = System.in.read(buffer); //讀取標準輸入流System.out.println("保存在緩沖區的元素個數為" + count);System.out.println("輸出 buffer 元素值:");for (int i = 0; i < count; i ++) {System.out.print(" " + buffer[i]);}System.out.println();System.out.println("輸出 buffer 字符元素:");System.out.write(buffer, 0, buffer.length);}}輸出如下:
下面做個小實驗,對該程序做幾點改變,看看有什么變化:
如此簡單一個程序,我以為搞懂了,可是回看一下課本上的說明,還是有問題滴:
PS:這個問題已得到解決,后面的程序(第三小節輸入輸出流類的應用里最后一個實驗)中會把字節數組轉換成字符串,這里寫好了就不動了吧,主要是懶,哈哈~~
二、輸入輸出流框架
課本上哇哇哇說了一大堆,實在沒什么可講的,就直接放圖吧:
數據流以輸入流的形式被程序獲取,再以輸出流的形式將數據輸出到其它設備。圖 1 為輸入流模式,圖 2 為輸出流模式:
輸入輸出流總框架圖:
最后提一下關于輸入輸出流的分類,了解即可:
數據流是 Java 進行 I/O 操作的對象,它按照不同的標準可以分為不同的類別。
三、輸入輸出流類的應用
課本程序 exp8.4
例 8.4:創建兩個 File 類的對象,分別判斷兩個文件是否存在;如果不存在,則新建。然后從鍵盤輸入字符數據存入數組 b 里,通過文件輸出流,把數組里的字符寫入到 hello1.txt 文件,再從 hello1.txt 中讀取數據,寫到文件 hello2.txt 中。以下是源代碼。
package big;import java.io.*;public class stream_exp8_4 {public static void main(String[] args) {int len;byte b[] = new byte[20]; //定義一個長度為20的字節型數組//創建文件對象(這里只是在程序中實例出對象,其實并不存在)File file1 = new File("D:\\學校課程學習\\java程序設計\\eclipse\\工作空間\\hello1.txt");File file2 = new File("D:\\學校課程學習\\java程序設計\\eclipse\\工作空間\\hello2.txt");FileOutputStream fos = null; //先定義,后面會在下面字節流應用中再實例化對象(new)的try { //如果文件不存在,就創建對象(經過這里的操作才是真的在 java 文件夾里創建了文件)if (!file1.exists())file1.createNewFile();if (!file2.exists());file2.createNewFile();//字節流應用System.out.println("請輸入你想存入file1文件的內容:");len = System.in.read(b); //從鍵盤輸入的字符存入內存的 b 數組里的個數(一邊實現了鍵盤輸入,一遍統計了字符個數)fos = new FileOutputStream(file1, true); //創建文件輸出流到到 file1fos.write(b, 0, len); //通過文件輸出流 fos 把 b 數組中數據寫入到 file1 文件尾部//字符流與緩沖流應用FileReader in = new FileReader(file1); //打開字符文件輸入流BufferedReader bin = new BufferedReader(in); //傳送數據到緩沖區(這一句代碼就是裝飾流,作用是加速讀的速度)FileWriter out = new FileWriter(file2, true); //打開字符文件輸出流String str;System.out.println("完美復制到file2文件中的內容:");while ((str = bin.readLine()) != null) { //將緩沖區中數據一行一行地送到字符串變量字符串變量 str 中System.out.println(str); //輸出 str 中數據到控制臺out.write(str+"\n"); //將 str 中數據寫入文件}out.close();in.close();fos.close(); //關閉流資源}catch(IOException e) {e.printStackTrace();}}}運行結果如下:
看著沒問題是吧,再試試重復運行輸入一遍。由此我們會發現打印在控制臺中的有兩個 “ 相信中國!” ,打開文件后發現 hello1.txt 里有兩個 “ 相信中國!” ,文件 hello2.txt 里有三個 “ 相信中國!” 。仔細想一想,也就該是這樣哈!
改寫 exp8.4(1)
OK,接下來,我們再來做些實驗,首先有一個問題是裝飾類只是加快了讀的速度,其實沒它照樣可以完成任務,我們這樣來改寫程序:
FileReader in = new FileReader(file1); //BufferedReader bin = new BufferedReader(in); //刪掉裝飾流 FileWriter out = new FileWriter(file2, true); for (int i = 0; i < len; i ++) {System.out.print((char)b[i]);out.write(b[i]); }這樣一來,運行結果會變成怎樣呢?結果是識別不了漢字了(英文倒是可以),另外就是不管運行幾遍,控制臺打印的都只會是本次運行時鍵盤輸入的內容,文本文件中也只會增加本次輸入的內容,大家可以對比著來看看:
不明白,為啥啊???
改寫 exp_8.4(2)
再來一個實驗:在示例中,我們輸出流用的是字節流,輸出流用的是字符流,統一一下不好嗎?我先來試試統一字節流輸入輸出好了。
終于,我成功了,就像寫高考數學題,寫的時候真難,寫完了發現好簡單😂😂😂
就在這個程序里,我把字節數組轉換成了字符串,順利地在控制臺(屏幕)上打印出來了(這也是為什么課上有同學問 “ 為什么可以用字節數組輸出漢字 ” 問題的答案了,都轉換成了字符串,那為什么還不能輸出漢語呢,是吧?)。大家看那輸入輸出流框架圖都是一愣一愣的,不過呢,這里有篇文章很好的總結了字節輸入輸出流的框架和方法,我就是照著這篇文章完成這個實驗的,分享一下。
???還有統一字符輸入輸出流???再說吧,累了。
四、RandomAccessFile 類
課上老師講:RandomAccessFile 類是一個隨機存取文件類。雖然不明白這句話什么意思,但下一句確實醍醐灌頂:這個類可以實現 Java 輸入輸出流的任意操作。我了個乖乖,相比較框架圖里那么多類,這樣子只用一個類就方便多了呀!
例 8.5 :通過 RandomAccessFile 類從文件的不同位置讀寫不同長度的數據,講字符串數據添加在文件尾部。
package big;import java.io.*;public class exp8_5 {public static void main(String[] args) {String str[] = {"First lint\n", "second line\n", "Last line\n"};try {//用 RandomAccessFile 類實例化出 rf 對象,參數表示可以對文件 demo.txt 進行讀寫操作RandomAccessFile rf = new RandomAccessFile("demo.txt", "rw"); System.out.println("\n光標的位置為:" + rf.getFilePointer()); //獲取文件指針位置方法System.out.println("文件的長度為:" + rf.length());rf.seek(rf.length()); //把光標移到文件末尾(用的是 seek 方法)System.out.println("光標現在的位置為:" + rf.getFilePointer());for (int i = 0; i < 3; i ++)rf.writeBytes(str[i]); //將字符串數組 str 里的三個字符串依次寫入 rf 對象中rf.seek(0); //把光標移到文件起始位置System.out.println("\n文件現在的內容:");String s;while ((s = rf.readLine()) != null) //分行讀取System.out.println(s); //分行打印rf.close(); //關閉流資源}catch (FileNotFoundException fnoe) {}catch (IOException ioe) {}} }運行結果和課本里的一樣:
以下摘自課本中的說明:
怎么說?其實沒什么,我打一遍代碼試著運行也是為了看看到底有多方便,也確實比原始輸入輸出流分開寫簡單許多。
其實還有一個小節講的是 “ 對象序列化與對象流類 ” ,課上老師好像也是一筆帶過(是不是啊?我沒有認真聽這點內容,感覺還沒講就過去了,連示例程序都沒啥印象)
輸入輸出流總結
我看課本上的小結講的是使用輸入輸出流的參考步驟和流程,但我就 get 不到,沒有感覺。看來還是對 Java 不熟悉,對輸入輸出流不熟悉( c++ 里不也是輸入輸出流 cin、cout 嗎?感覺就像一個在天上,一個在地下。。。)
在最后我還是說一下輸入輸出和讀寫的關系吧,我上機的時候就把輸入輸出流的意思給搞反了。記住一點:輸入輸出都是以程序為參照物的
- 輸入流:用于從鍵盤或文件(數據源)獲得數據傳遞給程序,只能讀不能寫;
- 輸出流:用于將數據從程序傳遞給數據接收者(宿點),如內存、顯示器屏幕、打印機或文件,只能寫不能讀。
Java 中一切名詞皆為類,一切類都要實例化對象,一切對象都有屬性和方法,Java 就是靠著對象的屬性和方法來完成編程解決問題的,這就是我學習 Java 以來的深刻體會,這就是面向對象編程!!!
總結
以上是生活随笔為你收集整理的Java 输入输出流学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 根据输入的银行卡号识别出银行名称并显示
- 下一篇: 基于手写数字识别的FGSM