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