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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

I/O流讲解

發(fā)布時(shí)間:2023/12/18 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 I/O流讲解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文來自:曹勝歡博客專欄:http://blog.csdn.net/csh624366188


????? 在軟件開發(fā)中,數(shù)據(jù)流和數(shù)據(jù)庫操作占據(jù)了一個(gè)很重要的位置,所以,熟悉操作數(shù)據(jù)流和數(shù)據(jù)庫,對于每一個(gè)開發(fā)者來說都是很重要的,今天就來總結(jié)一下I/O,數(shù)據(jù)庫操作

一:從數(shù)據(jù)流開始

首先先有一個(gè)結(jié)構(gòu)圖看一下整個(gè)數(shù)據(jù)流中的API結(jié)構(gòu)和對象繼承關(guān)系信息:


其他常用與流有關(guān)的對象:


首先從字符流開始

1、字符流的由來:

????因?yàn)槲募幋a的不同,而有了對字符進(jìn)行高效操作的字符流對象。

????原理:其實(shí)就是基于字節(jié)流讀取字節(jié)時(shí),去查了指定的碼表。

字節(jié)流和字符流的區(qū)別:

1,字節(jié)流讀取的時(shí)候,讀到一個(gè)字節(jié)就返回一個(gè)字節(jié)。字符流使用了字節(jié)流讀到一個(gè)或多個(gè)字節(jié)(中文對應(yīng)的字節(jié)數(shù)是兩個(gè),UTF-8碼表中是3個(gè)字節(jié))時(shí)。先去查指定的編碼表,將查到的字符返回。

2,字節(jié)流可以處理所有類型數(shù)據(jù),如圖片,mp3,avi。而字符流只能處理字符數(shù)據(jù)。

結(jié)論:只要是處理純文本數(shù)據(jù),就要優(yōu)先考慮使用字符流。除此之外都用

節(jié)流。

基本的讀寫操作方式:

因?yàn)閿?shù)據(jù)通常都以文件形式存在。

所以就要找到IO體系中可以用于操作文件的流對象。

通過名稱可以更容易獲取該對象。

因?yàn)镮O體系中的子類名后綴絕大部分是父類名稱。而前綴都是體現(xiàn)子類功能的名字。

Reader

???|--InputStreamReader

????????????|--FileReader:專門用于處理文件的字符讀取流對象。

Writer

????|--OutputStreamWriter

??????????????????|--FileWriter:專門用于處理文件的字符寫入流對象。

Reader中的常見的方法:

1,int?read():讀取一個(gè)字符。返回的是讀到的那個(gè)字符。如果讀到流的末尾,返回-1.

2,int?read(char[]):將讀到的字符存入指定的數(shù)組中,返回的是讀到的字符個(gè)數(shù),也就是往數(shù)組里裝的元素的個(gè)數(shù)。如果讀到流的末尾,返回-1.

3,close():讀取字符其實(shí)用的是window系統(tǒng)的功能,就希望使用完畢后,進(jìn)行資源的釋放

Writer中的常見的方法:

1,write(ch):?將一個(gè)字符寫入到流中。

2,write(char[]):?將一個(gè)字符數(shù)組寫入到流中。

3,write(String):?將一個(gè)字符串寫入到流中。

4,flush():刷新流,將流中的數(shù)據(jù)刷新到目的地中,流還存在。

5,close():關(guān)閉資源:在關(guān)閉前會先調(diào)用flush(),刷新流中的數(shù)據(jù)去目的地。然流關(guān)閉。

FileWriter:該類沒有特有的方法只有自己的構(gòu)造函數(shù)。該類特點(diǎn)在于

1,用于處理文本文件。

2,該類中有默認(rèn)的編碼表,

3,該類中有臨時(shí)緩沖。

構(gòu)造函數(shù):在寫入流對象初始化時(shí),必須要有一個(gè)存儲數(shù)據(jù)的目的地。

對于讀取或者寫入流對象的構(gòu)造函數(shù),以及讀寫方法,還有刷新關(guān)閉功能都會拋出IOException或其子類。所以都要進(jìn)行處理。或者throws拋出,或者try?catch處理

另一個(gè)小細(xì)節(jié):

當(dāng)指定絕對路徑時(shí),定義目錄分隔符有兩種方式:

1,反斜線但是一定要寫兩個(gè)。\\new?FileWriter("c:\\demo.txt");

2,斜線/??寫一個(gè)即可。new?FileWriter("c:/demo.txt");

一個(gè)讀取文本文件的經(jīng)典例子:

[java]?view plaincopy print?
  • <span?style="color:#000000;">FileReader?fr?=?null;??
  • try??
  • {??
  • fr?=?new?FileReader("demo.txt");??
  • char[]?buf?=?new?char[1024];//該長度通常都是1024的整數(shù)倍。??
  • int?len?=?0;??
  • while((len=fr.read(buf))!=-1)??
  • {??
  • System.out.println(new?String(buf,0,len));??
  • }??
  • }??
  • catch(IOException?e)??
  • {??
  • System.out.println(e.toString());??
  • }??
  • </span>??


  • 字符流的緩沖區(qū):緩沖區(qū)的出現(xiàn)提高了對流的操作效率。

    原理:其實(shí)就是將數(shù)組進(jìn)行封裝。

    對應(yīng)的對象:

    BufferedWriter:特有方法:newLine():跨平臺的換行符。

    BufferedReader:特有方法:readLine():一次讀一行,到行標(biāo)記時(shí),將行標(biāo)記之前的字符數(shù)據(jù)作為字符串返回。當(dāng)讀到末尾時(shí),返回null。

    在使用緩沖區(qū)對象時(shí),要明確,緩沖的存在是為了增強(qiáng)流的功能而存在,

    所以在建立緩沖區(qū)對象時(shí),要先有流對象存在。

    其實(shí)緩沖內(nèi)部就是在使用流對象的方法,只不過加入了數(shù)組對數(shù)據(jù)進(jìn)行了臨時(shí)存儲。為了提高操作數(shù)據(jù)的效率。

    代碼上的體現(xiàn):

    寫入緩沖區(qū)對象。

    //建立緩沖區(qū)對象必須把流對象作為參數(shù)傳遞給緩沖區(qū)的構(gòu)造函數(shù)。

    BufferedWriter?bufw?=?new?BufferedWriter(new?FileWriter("buf.txt"));

    bufw.write("abce");//將數(shù)據(jù)寫入到了緩沖區(qū)。

    bufw.flush();//對緩沖區(qū)的數(shù)據(jù)進(jìn)行刷新。將數(shù)據(jù)刷到目的地中。

    bufw.close();//關(guān)閉緩沖區(qū),其實(shí)關(guān)閉的是被包裝在內(nèi)部的流對象。

    讀取緩沖區(qū)對象。

    BufferedReader?bufr?=?new?BufferedReader(new?FileReader("buf.txt"));

    String?line?=?null;

    //按照行的形式取出數(shù)據(jù)。取出的每一個(gè)行數(shù)據(jù)不包含回車符。

    while((line=bufr.readLine())!=null)

    {

    System.out.println(line);

    }

    bufr.close();

    readLine():方法的原理:

    其實(shí)緩沖區(qū)中的該方法,用的還是與緩沖區(qū)關(guān)聯(lián)的流對象的read方法。只不過,每一次讀到一個(gè)字符,先不進(jìn)行具體操作,先進(jìn)行臨時(shí)存儲。當(dāng)讀取到回車標(biāo)記時(shí),將臨時(shí)容器中存儲的數(shù)據(jù)一次性返回。

    既然明確了原理,我們也可以實(shí)現(xiàn)一個(gè)類似功能的方法。

    [java]?view plaincopy print?
  • class?MyBufferedReader??
  • {??
  • private?Reader?r;??
  • MyBufferedReader(Reader?r)??
  • {??
  • this.r?=?r;??
  • }??
  • public?String?myReadLine()throws?IOException??
  • {//1,創(chuàng)建臨時(shí)容器。??
  • StringBuilder?sb?=?new?StringBuilder();??
  • //2,循環(huán)的使用read方法不斷讀取字符。??
  • int?ch?=?0;??
  • while((ch=r.read())!=-1)??
  • {??
  • if(ch=='\r')??
  • continue;??
  • if(ch=='\n')??
  • return?sb.toString();??
  • else??
  • sb.append((char)ch);??
  • }??
  • if(sb.length()!=0)??
  • return?sb.toString();??
  • return?null;??
  • }??
  • public?void?myClose()throws?IOException??
  • {??
  • r.close();??
  • }??
  • }??


  • 然后說一下字節(jié)流:

    抽象基類:InputStream,OutputStream。

    字節(jié)流可以操作任何數(shù)據(jù)。

    注意:字符流使用的數(shù)組是字符數(shù)組。char?[]?chs字節(jié)流使用的數(shù)組是字節(jié)數(shù)組。byte?[]?bt

    FileOutputStream?fos?=?new?FileOutputStream("a.txt");

    fos.write("abcde");//直接將數(shù)據(jù)寫入到了目的地。

    fos.close();//只關(guān)閉資源。

    FileInputStream?fis?=?new?FileInputStream("a.txt");

    //fis.available();//獲取關(guān)聯(lián)的文件的字節(jié)數(shù)。

    //如果文件體積不是很大。

    //可以這樣操作。

    byte[]?buf?=?new?byte[fis.available()];//創(chuàng)建一個(gè)剛剛好的緩沖區(qū)。

    //但是這有一個(gè)弊端,就是文件過大,大小超出jvm的內(nèi)容空間時(shí),會內(nèi)存溢出。

    ?????fis.read(buf);

    ?????一個(gè)小問題:

    字節(jié)流的read()方法讀取一個(gè)字節(jié)。為什么返回的不是byte類型,而是int類型呢?

    因?yàn)閞ead方法讀到末尾時(shí)返回的是-1,而在所操作的數(shù)據(jù)中的很容易出現(xiàn)連續(xù)多個(gè)1的情況,而連續(xù)讀到8個(gè)1,就是-1,導(dǎo)致讀取會提前停止。所以將讀到的一個(gè)字節(jié)給提升為一個(gè)int類型的數(shù)值,但是只保留原字節(jié),并在剩余二進(jìn)制位補(bǔ)0.

    對于write方法,可以一次寫入一個(gè)字節(jié),但接收的是一個(gè)int類型數(shù)值。只寫入該int類型的數(shù)值的最低一個(gè)字節(jié)(8位)。

    簡單說:read方法對讀到的數(shù)據(jù)進(jìn)行提升。write對操作的數(shù)據(jù)進(jìn)行轉(zhuǎn)換。這是神馬意思???

    轉(zhuǎn)換流:

    特點(diǎn):

    1,是字節(jié)流和字符流之間的橋梁。

    2,該流對象中可以對讀取到的字節(jié)數(shù)據(jù)進(jìn)行指定編碼表的編碼轉(zhuǎn)換。

    什么時(shí)候使用呢?

    1,當(dāng)字節(jié)和字符之間有轉(zhuǎn)換動作時(shí)。

    2,流操作的數(shù)據(jù)需要進(jìn)行編碼表的指定時(shí)。

    具體的對象體現(xiàn):

    1,InputStreamReader:字節(jié)到字符的橋梁。

    2,OutputStreamWriter:字符到字節(jié)的橋梁。

    這兩個(gè)流對象是字符流體系中的成員。

    那么它們有轉(zhuǎn)換作用,而本身又是字符流。所以在構(gòu)造的時(shí)候,需要傳入字節(jié)流對象進(jìn)來。

    構(gòu)造函數(shù):

    InputStreamReader(InputStream):通過該構(gòu)造函數(shù)初始化,使用的是本系統(tǒng)默認(rèn)的編碼表GBK。

    InputStreamReader(InputStream,String?charSet):通過該構(gòu)造函數(shù)初始化,可以指定編碼表。

    OutputStreamWriter(OutputStream):通過該構(gòu)造函數(shù)初始化,使用的是本系統(tǒng)默認(rèn)的編碼表GBK。

    OutputStreamWriter(OutputStream,String?charSet):通過該構(gòu)造函數(shù)初始化,可以指定編碼表。

    可以和流相關(guān)聯(lián)的集合對象Properties.

    Map

    ??|--Hashtable

    ?????|--Properties

    Properties:該集合不需要泛型,因?yàn)樵摷现械逆I值對都是String類型。

    1,存入鍵值對:setProperty(key,value);

    2,獲取指定鍵對應(yīng)的值:value?getProperty(key);

    3,獲取集合中所有鍵元素:

    Enumeration??propertyNames();

    在jdk1.6版本給該類提供一個(gè)新的方法。

    Set<String>?stringPropertyNames();

    4,列出該集合中的所有鍵值對,可以通過參數(shù)打印流指定列出到的目的地。

    list(PrintStream);

    list(PrintWriter);

    例:list(System.out):將集合中的鍵值對打印到控制臺。

    list(new?PrintStream("prop.txt")):將集合中的鍵值對存儲到prop.txt文件中。

    5,可以將流中的規(guī)則數(shù)據(jù)加載進(jìn)行集合,并稱為鍵值對。

    load(InputStream):

    jdk1.6版本。提供了新的方法。

    load(Reader):

    注意:流中的數(shù)據(jù)要是"鍵=值"?的規(guī)則數(shù)據(jù)。

    6,可以將集合中的數(shù)據(jù)進(jìn)行指定目的的存儲。

    store(OutputStram,String?comment)方法。

    jdk1.6版本。提供了新的方法。

    store(Writer?,String?comment):

    使用該方法存儲時(shí),會帶著當(dāng)時(shí)存儲的時(shí)間。

    File類:

    該類的出現(xiàn)是對文件系統(tǒng)的中的文件以及文件夾進(jìn)行對象的封裝。

    可以通過對象的思想來操作文件以及文件夾。

    1,構(gòu)造函數(shù):

    File(String?filename):將一個(gè)字符串路徑(相對或者絕對)封裝成File對象,該路徑是可存在的,也可以是不存在。

    File(String?parent,String?child);

    File(File?parent,String?child);

    2,特別的字段:separator:跨平臺的目錄分隔符。

    如:File?file?=?new?File("c:"+File.separator+"abc"+File.separator+"a.txt");

    3,常見方法:

    1,創(chuàng)建:

    boolean?createNewFile()throws?IOException:創(chuàng)建文件,如果被創(chuàng)建的文件已經(jīng)存在,則不創(chuàng)建。

    boolean?mkdir():?創(chuàng)建文件夾。

    boolean?mkdirs():?創(chuàng)建多級文件夾。

    2,刪除:

    boolean?delete():可用于刪除文件或者文件夾。

    注意:對于文件夾只能刪除不帶內(nèi)容的空文件夾,

    對于帶有內(nèi)容的文件夾,不可以直接刪除,必須要從里往外刪除。

    void?deleteOnExit():?刪除動作交給系統(tǒng)完成。無論是否反生異常,系統(tǒng)在退出時(shí)執(zhí)行刪除動作。

    3,判斷:

    boolean?canExecute():

    boolean?canWrite():

    boolean?canRead();

    boolean?exists():判斷文件或者文件夾是否存在。

    boolean?isFile():?判斷File對象中封裝的是否是文件。

    boolean?isDirectory():判斷File對象中封裝的是否是文件夾。

    boolean?isHidden():判斷文件或者文件夾是否隱藏。在獲取硬盤文件或者文件夾時(shí),

    對于系統(tǒng)目錄中的文件,Java是無法訪問的,所以在遍歷,可以避免遍歷隱藏文件。

    4,獲取:

    getName():獲取文件或者文件夾的名稱。

    getPath():File對象中封裝的路徑是什么,獲取的就是什么。

    getAbsolutePath():無論File對象中封裝的路徑是什么,獲取的都是絕對路徑。

    getParent():?獲取File對象封裝文件或者文件夾的父目錄。

    注意:如果封裝的是相對路徑,那么返回的是null.

    long?length():獲取文件大小。

    longlastModified():獲取文件或者文件最后一次修改的時(shí)間。

    static?File[]?listRoots():獲取的是被系統(tǒng)中有效的盤符。

    String[]?list():獲取指定目錄下當(dāng)前的文件以及文件夾名稱。

    String[]?list(Filenamefilter):?可以根據(jù)指定的過濾器,過濾后的文件及文件夾名稱。

    File[]?listFiles():獲取指定目錄下的文件以及文件夾對象。

    5,重命名:

    renameTo(File):

    File?f1?=?new?File("c:\\a.txt");

    File?f2?=?new?File("c:\\b.txt");

    f1.renameTo(f2);//將c盤下的a.txt文件改名為b.txt文件。

    對象的序列化。

    ObjectInputStream

    ObjectOutputStream

    可以通過這兩個(gè)流對象直接操作已有對象并將對象進(jìn)行本地持久化存儲。

    存儲后的對象可以進(jìn)行網(wǎng)絡(luò)傳輸。

    Serializable:該接口其實(shí)就是一個(gè)沒有方法的標(biāo)記接口。

    用于給類指定一個(gè)UID。該UID是通過類中的可序列化成員的數(shù)字簽名運(yùn)算出來的一個(gè)long型的值。

    只要是這些成員沒有變化,那么該值每次運(yùn)算都一樣。

    該值用于判斷被序列化的對象和類文件是否兼容。

    如果被序列化的對象需要被不同的類版本所兼容。可以在類中自定義UID。

    定義方式:static?final?long?serialVersionUID?=?42L;

    注意:對應(yīng)靜態(tài)的成員變量,不會被序列化。

    對應(yīng)非靜態(tài)也不想被序列化的成員而言,可以通過transient關(guān)鍵字修飾。

    通常,這兩個(gè)對象成對使用。

    ————————————————————————————————————

    其他的數(shù)據(jù)操作流

    操作基本數(shù)據(jù)類型的流對象。

    DataInputStream

    DataInputStream(InputStream);

    操作基本數(shù)據(jù)類型的方法:

    int?readInt():一次讀取四個(gè)字節(jié),并將其轉(zhuǎn)成int值。

    boolean?readBoolean():一次讀取一個(gè)字節(jié)。

    short?readShort();

    long?readLong();

    剩下的數(shù)據(jù)類型一樣。

    String?readUTF():按照utf-8修改版讀取字符。注意,它只能讀writeUTF()寫入的字符數(shù)據(jù)。

    DataOutputStream

    DataOutputStream(OutputStream):

    操作基本數(shù)據(jù)類型的方法:

    writeInt(int):一次寫入四個(gè)字節(jié)。

    注意和write(int)不同。write(int)只將該整數(shù)的最低一個(gè)8位寫入。剩余三個(gè)8位丟棄。

    writeBoolean(boolean);

    writeShort(short);

    writeLong(long);

    剩下是數(shù)據(jù)類型也也一樣。

    writeUTF(String):按照utf-8修改版將字符數(shù)據(jù)進(jìn)行存儲。只能通過readUTF讀取。

    通常只要操作基本數(shù)據(jù)類型的數(shù)據(jù)。就需要通過DataStram進(jìn)行包裝。

    通常成對使用。

    ————————————————————————————————————

    操作數(shù)組的流對象。

    1,操作字節(jié)數(shù)組

    ByteArrayInputStream

    ByteArrayOutputStream

    toByteArray();

    toString();

    writeTo(OutputStream);

    2,操作字符數(shù)組。

    CharArrayReader

    CharArrayWriter

    對于這些流,源是內(nèi)存。目的也是內(nèi)存。

    而且這些流并未調(diào)用系統(tǒng)資源。使用的就是內(nèi)存中的數(shù)組。

    所以這些在使用的時(shí)候不需要close。

    操作數(shù)組的讀取流在構(gòu)造時(shí),必須要明確一個(gè)數(shù)據(jù)源。所以要傳入相對應(yīng)的數(shù)組。

    對于操作數(shù)組的寫入流,在構(gòu)造函數(shù)可以使用空參數(shù)。因?yàn)樗鼉?nèi)置了一個(gè)可變長度數(shù)組作為緩沖區(qū)。

    總結(jié)

    以上是生活随笔為你收集整理的I/O流讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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