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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java 输入输出流学习总结

發(fā)布時(shí)間:2023/12/31 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 输入输出流学习总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 前言:為什么要有輸入輸出流
  • 一、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ù):

  • public abstract int read()
  • public int read (byte[] b)
  • public int read (byte[] b, int off, int len)
  • 輸入流結(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)改變,看看有什么變化:

  • 最后一行 write 方法中最后一個(gè)參數(shù)不應(yīng)該是 buffer.length-1 嗎?結(jié)果沒有任何改變,看來沒什么好說的了,我認(rèn)為 Java 不嚴(yán)謹(jǐn),支持我嗎,同志們?
  • 我不想在輸出 buffer 元素值時(shí)看到的是 ASCII 碼,我要看我輸入的字母。簡單,安排!這只是在 for 循環(huán)里面的輸入加上一個(gè)強(qiáng)制轉(zhuǎn)換符就行了System.out.print(" " + (char)buffer[i]);。問題是,多了兩行空格,這怎么解釋?🤔🤔🤔🤨🤨🤨
  • 如此簡單一個(gè)程序,我以為搞懂了,可是回看一下課本上的說明,還是有問題滴:

  • 我們在鍵盤上輸入7個(gè)字符,可是控制臺(tái)卻顯示保存在緩沖區(qū)的元素個(gè)數(shù)為 9,這是因?yàn)檫€有回車符 “ \r ” 占用了兩個(gè)元素,且元素值為 ASCII 碼值。(會(huì)不會(huì)那兩行空格就是因?yàn)檫@個(gè)原因?)
  • 對程序中的第一條注釋,原來課本里給出了說明:本例用到了 read(byte[] b) 方法,因其會(huì)產(chǎn)生輸入異常,可以放在 try···catch 塊中執(zhí)行,或令 main 方法將異常上交(即在聲明語句中加入 throws java.io.IOException ),這樣才能通過編譯。
  • 課本上說:本例使用了 write 方法直接輸出了字節(jié)數(shù)組的內(nèi)容,如果使用 println 方法可將字節(jié)數(shù)組的內(nèi)容轉(zhuǎn)換為字符串,否則不能正常顯示。于是把System.out.write(buffer, 0, buffer.length) 改成了下面這樣,但不行耶,老師怎么把字節(jié)數(shù)組里的內(nèi)容轉(zhuǎn)換成字符串啊?(我做了什么?最后為什么會(huì)有好多空格和 null 這幾個(gè)字符輸出?) :
  • String str = null; //如果不賦初始值 null 的話,將會(huì)報(bào)錯(cuò),原因是局部變量 str 尚未初始化 for (int i = 0; i < count; i ++) {str += (char)buffer[i]; } System.out.println(str);


    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)可以分為不同的類別。

  • 按照流的方向主要分為輸入流和輸出流兩大類;
  • 數(shù)據(jù)流按照數(shù)據(jù)單位的不同分為字節(jié)流和字符流;
  • 按照功能可以劃分為節(jié)點(diǎn)流和處理流;
  • 依據(jù)類的作用,可以分為文件流、緩沖流、數(shù)據(jù)流、管道流、轉(zhuǎ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)好簡單😂😂😂

    package big;import java.io.*;public class exp8_4_zijieliushurushuchu {public static void main(String[] args) {// TODO Auto-generated method stubint len;byte b[] = new byte[20];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;try {if (!file1.exists())file1.createNewFile();if (!file2.exists());file2.createNewFile();System.out.println("請輸入你想存入file1文件的內(nèi)容:");len = System.in.read(b);fos = new FileOutputStream(file1, true);fos.write(b, 0, len);FileInputStream in = new FileInputStream(file1);BufferedInputStream bin = new BufferedInputStream(in);FileOutputStream out = new FileOutputStream(file2, true); // for (int i = 0; i < len; i ++) { // out.write(b[i]); // }out.write(b); //上面三行 for 循環(huán)其實(shí)就是這一句話的事情,算是了解一下 write 方法吧String str = new String(b);System.out.println(str);out.close();in.close();fos.close();}catch(IOException e) {e.printStackTrace();} }}

    就在這個(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é)果和課本里的一樣:

    以下摘自課本中的說明:

  • 從本例看,隨機(jī)存取文件類的的使用方法,也是先建立文件流通道,打開文件,然后進(jìn)行讀寫操作,最后關(guān)閉文件通道。只是不用分輸入流和輸出流。
  • 可以用于多線程下載或多個(gè)線程同時(shí)寫數(shù)據(jù)到文件。
  • 怎么說?其實(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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。