瘋狂Java學(xué)習(xí)筆記(55)----------字節(jié)流與字符流

      網(wǎng)友投稿 961 2025-03-31

      瘋狂Java學(xué)習(xí)筆記(55)----------字節(jié)流與字符流

      字節(jié)流與字符流

      在java.io包中操作文件內(nèi)容的主要有兩大類:字節(jié)流、字符流,兩類都分為輸入和輸出操作。在字節(jié)流中輸出數(shù)據(jù)主要是使用OutputStream完成,輸入使的是InputStream,在字符流中輸出主要是使用Writer類完成,輸入流主要使用Reader類完成。(這四個(gè)都是抽象類)

      處理流的用法:

      按照流是否直接與特定的地方(如磁盤、內(nèi)存、設(shè)備等)相連,分為節(jié)點(diǎn)流和處理流兩類。

      節(jié)點(diǎn)流:可以從或向一個(gè)特定的地方(節(jié)點(diǎn))讀寫數(shù)據(jù)。如FileReader

      處理流:是對(duì)一個(gè)已存在的流的連接和封裝,通過所封裝的流的功能調(diào)用實(shí)現(xiàn)數(shù)據(jù)讀寫。

      如BufferedReader。處理流的構(gòu)造方法總是要帶一個(gè)其他的流對(duì)象做參數(shù)。一個(gè)流對(duì)象經(jīng)過其他流的多次包裝,稱為流的鏈接。

      常用的節(jié)點(diǎn)流

      父 ?類 ?InputStream OutputStream Reader Writer

      文 ?件 ?*FileInputStream FileOutputStrean FileReader FileWriter 文件進(jìn)行處理的節(jié)點(diǎn)流

      數(shù) ?組 ?*ByteArrayInputStream ?ByteArrayOutputStream ?CharArrayReader ?CharArrayWriter

      對(duì)數(shù)組進(jìn)行處理的節(jié)點(diǎn)流(對(duì)應(yīng)的不再是文件,而是內(nèi)存中的一個(gè)數(shù)組)

      字符串 ?*無 ? ?無 ?StringReader StringWriter 對(duì)字符串進(jìn)行處理的節(jié)點(diǎn)流

      管 ?道 ?*PipedInputStream ?PipedOutputStream ?PipedReader ?PipedWriter 對(duì)管道進(jìn)行處理的節(jié)點(diǎn)流

      常用處理流(關(guān)閉處理流使用關(guān)閉里面的節(jié)點(diǎn)流)

      父 ?類 ?InputStream OutputStream Reader Writer

      緩沖流 ?*BufferedImputStrean BufferedOutputStream BufferedReader BufferedWriter ----需要父類作為參數(shù)構(gòu)造,增加緩沖功能,避免頻繁讀寫硬盤,可以初始化緩沖數(shù)據(jù)的大小,由于帶了緩沖功能,所以就寫數(shù)據(jù)的時(shí)候需要使用flush方法。

      轉(zhuǎn)換流 ?*InputStreamReader ?OutputStreamWriter- ?要inputStream 或OutputStream作為參數(shù),實(shí)現(xiàn)從字節(jié)流到字符流的轉(zhuǎn)換?數(shù)據(jù)流 ?*DataInputStream DataOutputStream -提供將基礎(chǔ)數(shù)據(jù)類型寫入到文件中,或者讀取出來,為什么要有這個(gè)流呢?

      瘋狂Java學(xué)習(xí)筆記(55)----------字節(jié)流與字符流

      看這樣的分析,如果沒有這種流的話,有一個(gè)long,本身只占8個(gè)字節(jié),如果我要寫入到文件,需要轉(zhuǎn)成字符串,然后在轉(zhuǎn)成字符數(shù)組,那空間會(huì)占用很多,但是有了這種流之后就很方便了,直接將這8個(gè)字節(jié)寫到文件就完了。。是不是既節(jié)約了內(nèi)存空間有讓程序?qū)懫饋砀臃奖愫?jiǎn)單了吶。寫倒是很簡(jiǎn)單,但是讀取的時(shí)候就注意了,根據(jù)讀取的數(shù)據(jù)類型,指針會(huì)往下移,所以你寫的順序必須要和讀的順序一致才能完成你正確的需求。

      因此,我們使用處理流時(shí)的典型思路是:使用處理流來包裝字節(jié)流,程序通過處理流來執(zhí)行輸入/輸出功能,讓字節(jié)流與底層的I/O設(shè)備、文件進(jìn)行交互。

      輸入輸出流體系:

      Java的輸入輸出流提供了近40個(gè)類:看似毫無規(guī)律,但我們可以按功能劃分:如下圖:

      通常來說,字節(jié)流的功能比字符流的功能強(qiáng)大,因?yàn)橛?jì)算機(jī)里的所有數(shù)據(jù)都是二進(jìn)制的,你懂得!

      但我還是喜歡字符流,直接明了。

      轉(zhuǎn)換流

      兩個(gè)轉(zhuǎn)換流:

      1.將字節(jié)轉(zhuǎn)換成字符流

      InputStreamReader:將字節(jié)輸入流轉(zhuǎn)換成字符輸入流,OutPutStreamWriter:將字節(jié)輸出流轉(zhuǎn)換成字符輸出流

      2.從字符流到字節(jié)流:可以從字符流中獲取char[]數(shù)組,轉(zhuǎn)換為String,然后調(diào)用String的API函數(shù)getBytes() 獲取到byte[],然后就可以通過ByteArrayInputStream、ByteArrayOutputStream來實(shí)現(xiàn)到字節(jié)流的轉(zhuǎn)換。

      package com.haixu.io;

      import java.io.BufferedReader;

      import java.io.InputStreamReader;

      public class KeyinTest {

      public static void main(String[] args) {

      try {

      //將system.in對(duì)象轉(zhuǎn)換成Reader對(duì)象

      System.out.println("請(qǐng)輸入:");

      InputStreamReader reader = new InputStreamReader(System.in);

      //將Reader對(duì)象轉(zhuǎn)換成BufferedReader對(duì)象

      BufferedReader br = new BufferedReader(reader);

      String buffer = null;

      //進(jìn)行逐行的讀取

      while((buffer = br.readLine()) != null){

      //如果讀取的內(nèi)容為exit,則退出程序

      if(buffer.equals("exit")){

      System.exit(1);

      }

      System.out.println("輸入內(nèi)容為:" + buffer);

      }

      } catch (Exception e) {

      // TODO: handle exception

      e.printStackTrace();

      }

      finally{reader.close();br.close()}//不要忘記關(guān)閉流 我忘記了,后加入的!

      弄點(diǎn)高大尚的:

      推回輸入流

      在輸入輸出流中,有兩個(gè)特殊的流:? PushbackInputStream 和? PushbackReader

      Pushback用于輸入流允許字節(jié)被讀取然后返回(即“推回”)到流。PushbackInputStream類實(shí)現(xiàn)了這個(gè)想法。它提供了一種機(jī)制來“窺視”在沒有受到破壞的情況下輸入流生成了什么。

      PushbackInputStream有兩個(gè)構(gòu)造函數(shù):

      PushbackInputStream(InputStream inputStream)

      PushbackInputStream(InputStream inputStream, int numBytes)

      第一種形式創(chuàng)建了一個(gè)允許一個(gè)字節(jié)推回到輸入流的流對(duì)象。第二種形式創(chuàng)建了一個(gè)具有numBytes長(zhǎng)度緩沖區(qū)的推回緩沖流。它允許多個(gè)字節(jié)推回到輸入流。除了具有與InputStream相同的方法,PushbackInputStream提供了unread( )方法,表示如下:

      void unread(int ch)

      void unread(byte buffer[ ])

      void unread(byte buffer, int offset, int numChars)

      第一種形式推回ch的低位字節(jié),它將是隨后調(diào)用read( )方法所返回的下一個(gè)字節(jié)。第二種形式返回buffer緩沖器中的字節(jié)。第三種形式推回buffer中從offset處開始的numChars個(gè)字節(jié)。如果在推回緩沖器為滿時(shí)試圖返回一個(gè)字節(jié),IOException異常將被引發(fā)。Java 2 對(duì)PushbackInputStream作了一些小的修改:它實(shí)現(xiàn)skip( )方法。

      實(shí)例:

      package com.haixu.io;

      import java.io.FileReader;

      import java.io.PushbackReader;

      public class PushBackTest {

      /**

      * 推回輸入流練習(xí)

      *

      * */

      public static void main(String[] args) {

      try {

      /*

      * 創(chuàng)建推回輸入流的對(duì)象,并設(shè)定緩存的大小為:64字節(jié)

      * */

      PushbackReader pr = new PushbackReader(

      new FileReader("E://Java編程//Java06//src//com//haixu//io//PushbackTest.java") , 64);

      char [] buf = new char[64];

      //用于保存上次讀取的字符串內(nèi)容

      String lastContent = "";

      int hasRead = 0;

      //循環(huán)讀取文件內(nèi)容

      while((hasRead = pr.read(buf)) > 0 ){

      String content = new String(buf , 0 , hasRead);

      int targetIndex = 0 ;

      //將上次讀取的內(nèi)容與本次讀取的內(nèi)容拼接起來

      //查看是否包含目標(biāo)字符串,如果包含目標(biāo)字符串

      if((targetIndex = (lastContent + content).indexOf("new PushbackReader"))>0){

      //將本次內(nèi)容與上次內(nèi)容一起推回緩沖區(qū)

      pr.unread((lastContent + content).toCharArray());

      int len = targetIndex >32 ? 32 : targetIndex;

      //指定讀取指定長(zhǎng)度的內(nèi)容

      pr.read(buf , 0 , len);

      //打印輸出

      System.out.println(new String(buf ,0 , len));

      System.exit(0);

      }else{

      System.out.println(lastContent);

      //將本次內(nèi)容設(shè)定上次讀取的內(nèi)容

      lastContent = content;

      }

      }

      } catch (Exception e) {

      // TODO: handle exception

      e.printStackTrace();

      }

      }

      }

      重定向輸入輸出

      Java的標(biāo)準(zhǔn)輸入/輸出分別通過System.in和System.out來代表,在默認(rèn)的情況下分別代表鍵盤和顯示器,當(dāng)程序通過System.in來獲得輸入時(shí),實(shí)際上是通過鍵盤獲得輸入。當(dāng)程序通過System.out執(zhí)行輸出時(shí),程序總是輸出到屏幕。

      在System類中提供了三個(gè)重定向標(biāo)準(zhǔn)輸入/輸出的方法

      static void setErr(PrintStream err) 重定向“標(biāo)準(zhǔn)”錯(cuò)誤輸出流

      static void setIn(InputStream in)??? 重定向“標(biāo)準(zhǔn)”輸入流

      static void setOut(PrintStream out)重定向“標(biāo)準(zhǔn)”輸出流

      package com.haixu.io;

      import java.io.FileOutputStream;

      import java.io.PrintStream;

      public class RedirectOut {

      public static void main(String[] args) {

      try {

      /*

      * 一次性創(chuàng)建PrintStream輸出流

      */

      PrintStream ps = new PrintStream(new FileOutputStream("out.text"));

      //將標(biāo)準(zhǔn)輸入重定向到ps輸入流中

      System.setOut(ps);

      //向標(biāo)準(zhǔn)輸入一個(gè)字符串

      System.out.println("普通字符串");

      //向標(biāo)準(zhǔn)輸出輸出一個(gè)對(duì)象

      System.out.println((new RedirectOut()));

      } catch (Exception e) {

      // TODO: handle exception

      e.printStackTrace();

      }

      }

      }

      package com.haixu.io;

      import java.io.FileInputStream;

      import java.util.Scanner;

      public class RedirectIN {

      public static void main(String[] args) {

      try {

      //創(chuàng)建FileInputStreamd對(duì)象

      FileInputStream fis = new FileInputStream("E://Java編程//Java06//src//com//haixu//io//RedirectIN.java");

      //標(biāo)準(zhǔn)的輸入重定向到fis輸入流

      System.setIn(fis);

      //使用System.in創(chuàng)建Scanner對(duì)象,用于標(biāo)準(zhǔn)的輸入

      Scanner sc = new Scanner(System.in);

      //回車

      sc.useDelimiter("/n");

      while(sc.hasNext()){

      System.out.println("鍵盤輸入的內(nèi)容" + sc.next());

      }

      } catch (Exception e) {

      // TODO: handle exception

      e.printStackTrace();

      }

      }

      }

      RandomAccessFile

      RandomAccessFile是用來訪問那些保存數(shù)據(jù)記錄的文件的,你就可以用seek( )方法來訪問記錄,并進(jìn)行讀寫了。這些記錄的大小不必相同;但是其大小和位置必須是可知的。但是該類僅限于操作文件。

      RandomAccessFile不屬于InputStream和OutputStream類系的。實(shí)際上,除了實(shí)現(xiàn)DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也實(shí)現(xiàn)了這兩個(gè)接口),它和這兩個(gè)類系毫不相干,甚至不使用InputStream和OutputStream類中已經(jīng)存在的任何功能;它是一個(gè)完全獨(dú)立的類,所有方法(絕大多數(shù)都只屬于它自己)都是從零開始寫的。這可能是因?yàn)镽andomAccessFile能在文件里面前后移動(dòng),所以它的行為與其它的I/O類有些根本性的不同??偠灾?,它是一個(gè)直接繼承Object的,獨(dú)立的類。

      基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream結(jié)合起來,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移動(dòng)用的seek( ),以及判斷文件大小的length( )、skipBytes()跳過多少字節(jié)數(shù)。此外,它的構(gòu)造函數(shù)還要一個(gè)表示以只讀方式("r"),還是以讀寫方式("rw")打開文件的參數(shù) (和C的fopen( )一模一樣)。它不支持只寫文件。

      只有RandomAccessFile才有seek搜尋方法,而這個(gè)方法也只適用于文件。BufferedInputStream有一個(gè)mark( )方法,你可以用它來設(shè)定標(biāo)記(把結(jié)果保存在一個(gè)內(nèi)部變量里),然后再調(diào)用reset( )返回這個(gè)位置,但是它的功能太弱了,而且也不怎么實(shí)用。

      內(nèi)存映射文件

      內(nèi)存映射文件能讓你創(chuàng)建和修改那些因?yàn)樘蠖鵁o法放入內(nèi)存的文件。有了內(nèi)存映射文件,你就可以認(rèn)為文件已經(jīng)全部讀進(jìn)了內(nèi)存,然后把它當(dāng)成一個(gè)非常大的數(shù)組來訪問。這種解決辦法能大大簡(jiǎn)化修改文件的代碼。

      fileChannel.map(FileChannel.MapMode mode, long position, long size)將此通道的文件區(qū)域直接映射到內(nèi)存中。注意,你必須指明,它是從文件的哪個(gè)位置開始映射的,映射的范圍又有多大;也就是說,它還可以映射一個(gè)大文件的某個(gè)小片斷。

      MappedByteBuffer是ByteBuffer的子類,因此它具備了ByteBuffer的所有方法,但新添了force()將緩沖區(qū)的內(nèi)容強(qiáng)制刷新到存儲(chǔ)設(shè)備中去、load()將存儲(chǔ)設(shè)備中的數(shù)據(jù)加載到內(nèi)存中、isLoaded()位置內(nèi)存中的數(shù)據(jù)是否與存儲(chǔ)設(shè)置上同步。這里只簡(jiǎn)單地演示了一下put()和get()方法,除此之外,你還可以使用asCharBuffer( )之類的方法得到相應(yīng)基本類型數(shù)據(jù)的緩沖視圖后,可以方便的讀寫基本類型數(shù)據(jù)。

      /*

      * 程序功能:演示了RandomAccessFile類的操作,同時(shí)實(shí)現(xiàn)了一個(gè)文件復(fù)制操作。

      */

      package com.lwj.demo;

      import java.io.*;

      public class RandomAccessFileDemo {

      public static void main(String[] args) throws Exception {

      RandomAccessFile file = new RandomAccessFile("file", "rw");

      // 以下向file文件中寫數(shù)據(jù)

      file.writeInt(20);// 占4個(gè)字節(jié)

      file.writeDouble(8.236598);// 占8個(gè)字節(jié)

      file.writeUTF("這是一個(gè)UTF字符串");// 這個(gè)長(zhǎng)度寫在當(dāng)前文件指針的前兩個(gè)字節(jié)處,可用readShort()讀取

      file.writeBoolean(true);// 占1個(gè)字節(jié)

      file.writeShort(395);// 占2個(gè)字節(jié)

      file.writeLong(2325451l);// 占8個(gè)字節(jié)

      file.writeUTF("又是一個(gè)UTF字符串");

      file.writeFloat(35.5f);// 占4個(gè)字節(jié)

      file.writeChar('a');// 占2個(gè)字節(jié)

      file.seek(0);// 把文件指針位置設(shè)置到文件起始處

      // 以下從file文件中讀數(shù)據(jù),要注意文件指針的位置

      System.out.println("——————從file文件指定位置讀數(shù)據(jù)——————");

      System.out.println(file.readInt());

      System.out.println(file.readDouble());

      System.out.println(file.readUTF());

      file.skipBytes(3);// 將文件指針跳過3個(gè)字節(jié),本例中即跳過了一個(gè)boolean值和short值。

      System.out.println(file.readLong());

      file.skipBytes(file.readShort()); // 跳過文件中“又是一個(gè)UTF字符串”所占字節(jié),注意readShort()方法會(huì)移動(dòng)文件指針,所以不用加2。

      System.out.println(file.readFloat());

      //以下演示文件復(fù)制操作

      System.out.println("——————文件復(fù)制(從file到fileCopy)——————");

      file.seek(0);

      RandomAccessFile fileCopy=new RandomAccessFile("fileCopy","rw");

      int len=(int)file.length();//取得文件長(zhǎng)度(字節(jié)數(shù))

      byte[] b=new byte[len];

      file.readFully(b);

      fileCopy.write(b);

      System.out.println("復(fù)制完成!");

      }

      }

      /**

      *

      * @param skip 跳過多少過字節(jié)進(jìn)行插入數(shù)據(jù)

      * @param str 要插入的字符串

      * @param fileName 文件路徑

      */

      public static void beiju(long skip, String str, String fileName){

      try {

      RandomAccessFile raf = new RandomAccessFile(fileName,"rw");

      if(skip < 0 || skip > raf.length()){

      System.out.println("跳過字節(jié)數(shù)無效");

      return;

      }

      byte[] b = str.getBytes();

      raf.setLength(raf.length() + b.length);

      for(long i = raf.length() - 1; i > b.length + skip - 1; i--){

      raf.seek(i - b.length);

      byte temp = raf.readByte();

      raf.seek(i);

      raf.writeByte(temp);

      }

      raf.seek(skip);

      raf.write(b);

      raf.close();

      } catch (Exception e) {

      e.printStackTrace();

      }

      }

      Java 數(shù)據(jù)結(jié)構(gòu)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:pdf表格怎么轉(zhuǎn)換成word(pdf表格怎么轉(zhuǎn)換成word空白處怎么輸入文字)
      下一篇:Docker 操作指南之運(yùn)行命令篇
      相關(guān)文章
      亚洲AV成人无码久久精品老人| 亚洲国产成人在线视频| 亚洲男女一区二区三区| 亚洲av无码专区在线播放| 亚洲午夜激情视频| 中文字幕中韩乱码亚洲大片| 国产精品亚洲w码日韩中文| 亚洲精品无码专区久久同性男| 国产精品亚洲综合网站| 在线观看国产一区亚洲bd| 亚洲AV成人精品日韩一区| 亚洲AV无码之国产精品| 亚洲国产无线乱码在线观看| 亚洲欧美成人综合久久久| 亚洲变态另类一区二区三区| 亚洲1区2区3区精华液| 久久亚洲中文无码咪咪爱| 亚洲AV网一区二区三区| 亚洲AV蜜桃永久无码精品| 亚洲成?Ⅴ人在线观看无码| 亚洲精品国产V片在线观看| 亚洲精品专区在线观看| 亚洲愉拍99热成人精品热久久 | 国产成人亚洲综合无码| 久久亚洲欧洲国产综合| 一本久久a久久精品亚洲| 亚洲自偷自偷在线制服 | 亚洲人成网站色在线入口| 国产黄色一级毛片亚洲黄片大全| 亚洲一区无码精品色| 综合亚洲伊人午夜网 | 亚洲中文字幕无码一区二区三区| 亚洲一区爱区精品无码| 亚洲AV中文无码乱人伦下载| 亚洲a一级免费视频| 亚洲小视频在线播放| 亚洲色无码国产精品网站可下载| 亚洲精品无码久久久久久| 亚洲AV成人潮喷综合网| 曰韩亚洲av人人夜夜澡人人爽 | 五月天网站亚洲小说|