天天看點

java清空inputstream中的流_Java 流處理

資料流

1、I/O流概述

大部分程式都需要輸入/輸出處理,比如從鍵盤讀取資料、向螢幕中輸出資料、從檔案中讀或者向檔案中寫資料、在一個網絡連接配接上進行讀寫操作等。在Java中,把這些不同類型的輸入、輸出源抽象為流(Stream),而其中輸入或輸出的資料則稱為資料流(Data Stream),用統一的接口來表示,進而使程式設計簡單明了。

流一般分為輸入流(Input Stream)和輸出流(Output Stream)兩類,但這種劃分并不是絕對的。比如一個檔案,當向其中寫資料時,它就是一個輸出流;當從其中讀取資料時,它就是一個輸入流。當然,鍵盤隻是一個輸入流,而螢幕則隻是一個輸出流。

在Java開發環境中,主要是由包java.io中提供的一系列的類和接口來實作輸入/輸出處理。标準輸入/輸出處理則是由包java.lang中提供的類來處理的,但這些類又都是從包java.io中的類繼承而來。

輸入流:資料提供者,可從中讀取資料出來

輸出流:資料接收者,可往其中寫資料

2、位元組流

java清空inputstream中的流_Java 流處理

①位元組流的基類

Java中每一種位元組流的基本功能依賴于基本類InputStream和OutputStream,它們是抽象類,不能直接使用。

屬于InputStream類的方法有:

read():從流中讀入資料

int read():從輸入流中讀一個位元組,形成一個0~255之間的整數傳回(是一個抽象方法)。

int read(byte b[]):讀多個位元組到數組中,填滿整個數組。

int read(byte b[], int off, int len):從輸入流中讀取長度為len的資料,寫入數組b中從索引off開始的                    位置,并傳回讀取得位元組數。

對于這三個方法,若傳回-1,表明流結束,否則,傳回實際讀取的位元組數。

skip():跳過流中若幹位元組數

available():傳回流中可用位元組數

mark():在流中标記一個位置

reset():傳回标記過的位置

markSupport():是否支援标記和複位操作

close():關閉流

屬于OutputStream類的方法有:

write(int b):将一個整數輸出到流中(隻輸出低位位元組,為抽象方法)

write(byte b[]):将位元組數組中的資料輸出到流中

write(byte b[], int off, int len):将數組b中從off指定的位置開始,長度為len的資料輸出到流中

flush():刷空輸出流,并将緩沖區中的資料強制送出

close():關閉流

Writer的方法:write(String s), write(String s, int off, int len)

例:把輸入流中的所有内容複制到輸出流中

java清空inputstream中的流_Java 流處理

②檔案流

在I/O進行中,最常見的就是對檔案的操作。java.io包中所提供的檔案操作類包括:

用于讀寫本地檔案系統中的檔案:FileInputStream、FileOutputStream

(1)FileInputStream類用來打開一個輸入檔案,若要打開的檔案不存在,則會産生例外FileNotFoundException,這是一個非運作時例外,必須捕獲或聲明抛棄;

(2)FileOutputStream類用來打開一個輸出檔案,若要打開的檔案不存在,則會建立一個新的檔案,否則原檔案的内容會被新寫入的内容所覆寫。

(3)在進行檔案的讀/寫操作時,會産生非運作時例外IOException,必須捕獲或聲明抛棄(其它的輸入/輸出流處理時也同樣需要進行輸入/輸出例外處理)。

檔案流的構造方法:

FileInputStream(File f)            打開一個以f描述的檔案作為輸入。

FileInputStream(String name)             打開一個檔案路徑名為name的檔案作為輸入。

FileOutputStream(File f)            建立一個以f描述的檔案作為輸出,檔案如果已經存在,則其内容被清空。

FileOutputStream(String name)            建立一個檔案路徑名為name的檔案作為輸出,檔案如果已經存在,則其内容被清空。

FileOutputStream(String name, boolean append)            建立一個檔案路徑名為name的檔案作為輸出,檔案如果已經存在,則在該輸出上輸出的内容被接到原有内容之後。

例:File f1 = new File(“file1.txt”);

File f2 = newFile(“file2.txt”);

FileInputStream in=new FileInputStream(f1);

FileOutputStream out=new FileOutputStream(f2);

FileOutputStream out=new FileOutputStream(“file3.txt”);

輸入流的參數是用于指定輸入的檔案名,輸出流的參數則是用于指定輸出的檔案名。

java清空inputstream中的流_Java 流處理

将一個檔案複制到另一個檔案中(覆寫)

java清空inputstream中的流_Java 流處理

把一個檔案的内容加到另一個檔案後

描述本地檔案系統中的檔案或目錄:File、FileDescriptor

接口,主要用于實作檔案名查找模式的比對:FilenameFilter

提供對本地檔案系統中檔案的随機通路支援:RandomAccessFile

③過濾流: 緩沖流、資料流、其他過慮流

java.io中提供類FilterInputStream和FilterOutputStream分别對其他輸入/輸出流進行特殊處理,它們在讀/寫資料的同時可以對資料進行特殊處理。另外還提供了同步機制,使得某一時刻隻有一個線程可以通路一個輸入/輸出流。

類FilterInputStream和FilterOutputStream分别重寫了父類InputStream和OutputStream的所有方法,同時,它們的子類也應該重寫它們的方法以滿足特定的需要。

要使用過濾流,首先必須把它連接配接到某個輸入/輸出流上,通常在構造方法的參數中指定所要連接配接的流:protectedFilterInputStream(InputStreamin);        protectedFilterOutputStream(OutputStreamout);

(1)緩沖流:類BufferedInputStream和BufferedOutputStream實作了帶緩沖的過濾流,它提供了緩沖機制,把任意的I/O流“捆綁”到緩沖流上,可以提高該I/O流的讀取效率。

在初始化時,除了要指定所連接配接的I/O流之外,還可以指定緩沖區的大小。預設時是用32位元組大小的緩沖區;最優的緩沖區大小常依賴于主機作業系統、可使用的記憶體空間以及機器的配置等;一般緩沖區的大小為記憶體頁或磁盤塊等的整數倍,如8912位元組或更小。BufferedInputStream(InputStream in[, int size])                              BufferedOutputStream(OutputStream out[, int size])

對于BufferedOutputStream,隻有緩沖區滿時,才會将資料真正送到輸出流,但可以使用flush()方法人為地将尚未填滿的緩沖區中的資料送出。

将緩沖流與檔案流相接:FileInputStream  in = new   FileInputStream(“file1.txt”);

FileOutputStream out = new FileOutputStream (“file2.txt”);

BufferedInputStream bin = new BufferedInputStream(in,256)

BufferedOutputStream bout = new BufferedOutputStream(out,256);

int len;

byte bArray[]=new byte[256];

len=bin.read(bArray);      //len中得到的是實際讀取的長度, bArray中得到的是資料

out.flush(); //最後一次讀取的資料可能不到4096位元組

(2)資料流:接口DataInput和DataOutput,設計了一種較為進階的資料輸入輸出方式:除了可處理位元組和位元組數組外,還可以處理int、float、boolean等基本資料類型,這些資料在檔案中的表示方式和它們在記憶體中的一樣,無須轉換,如read(), readInt(), readByte() …;write(), writeChar(), writeBoolean()…。此外,還可以用readLine()方法讀取一行資訊。

DataInput:boolean    readBoolean()    byte readByte()    short    readShort()    char readChar()    int readInt()  long readLong()    double    readDouble() float    readFloat()    int readUnsignedByte()    int readUnsignedShort()    void readFully(byte[] b):讀滿位元組數組,不同于InputStream.read    void readFully(byte[]b, int off, int len) :讀滿指定長度,不同于InputStream.read    int skipBytes(int n):與InputStream.skip等價    String readUTF():安類UTF-8形式從輸入中讀取字元串    StringreadLine():按回車(\r)換行(\n)為分割符讀取一行字元串,不完全支援UNICODE

DataOutput:void writeBoolean(boolean v)    void writeByte(intv)    void writeShort(intv)

void writeChar(intv)    void writeInt(intv)    void writeLong(longv)    void writeFloat(floatv)

void writeDouble(double v)    void write(byte[] b):與OutputStream.write同義

void write(byte[] b, int off, int len):與OutputStream.write同義

void write(int b):與OutputStream.write同義

void writeBytes(Strings):隻輸出每個字元的低8位;不完全支援UNICODE。

void writeChars(Strings):每個字元在輸出中都占兩個位元組。

資料流可以連接配接一個已經建立好的資料對象,例如網絡的連結、檔案等。資料流可通過如下方式建立:

FileInputStream fis= new FileInputStream("file1.txt");

FileOutputStream fos= new FileOutputStream("file2.txt");

DataInputStream dis = new DataInputStream(fis);

DataOutputStream dos = new DataOutputStream(fos);

java清空inputstream中的流_Java 流處理

利用方法readLine()計算一個輸入流中的字元數和行數

(3)其他過慮流:LineNumberInputStream:主要用于對文本檔案的處理,提供了行号控制功能。已經被LineNumberReader取代PushBackInputStream:在編譯程式的詞法分析階段,經常要超前讀入一個位元組以界定目前詞的屬性,然後再将該位元組退回(因為下面的處理可能還會用到該位元組)。PushBackInputStream就提供了這樣的能力,它提供了一個方法将剛剛讀入的位元組退回到輸入流中去。PrintStream:其作用是将Java語言中的不同類型的資料以字元表示形式輸出到相應的輸出流中去。不産生異常。可自動flush。通過checkError()檢查錯誤。

④标準流

語言包java.lang中的System類管理标準輸入/輸出流和錯誤流。

System.in,從InputStream中繼承而來,用于從标準輸入裝置中擷取輸入資料(通常是鍵盤)。

System.out,從PrintStream中繼承而來,把輸出送到預設的顯示裝置(通常是顯示器)。

System.err,也是從PrintStream中繼承而來,把錯誤資訊送到預設的顯示裝置(通常是顯示器)。

每當main方法被執行時,就自動生成上述三個對象。

java清空inputstream中的流_Java 流處理

從鍵盤中擷取資料

⑤對象流

對象的持續性(Persistence):能夠紀錄自己的狀态以便将來再生的能力,叫對象的持續性。

對象的串行化(Serialization):對象通過寫出描述自己狀态的的數值來記錄自己的過程叫串行化。串行化的主要任務是寫出對象執行個體變量的數值,如果變量是另一個對象的引用,則引用的對象也要串行化。這個過程是遞歸的。

對象流:能夠輸入輸出對象的流稱為對象流。可以将對象串行化後通過對象輸入輸出流寫入檔案或傳送到其它地方。

在Java中,允許可串行化的對象在通過對象流進行傳輸。隻有實作Serializable接口的類才能被串行化,Serializable接口中沒有任何方法,當一個類聲明實作Serializable接口時,隻是表明該類加入對象串行化協定。

java清空inputstream中的流_Java 流處理

要串行化一個對象,必須與一定的對象輸出/輸入流聯系起來,通過對象輸出流将對象狀态儲存下來(将對象儲存到檔案中,或者通過網絡傳送到其他地方) ,再通過對象輸入流将對象狀态恢複。類ObjectOutputStream和ObjectInputStream分别繼承了接口ObjectOutput和ObjectInput,将資料流功能擴充到可以讀寫對象,前者用writeObject()方法可以直接将對象儲存到輸出流中,而後者用readObject()方法可以直接從輸入流中讀取一個對象。

定制對象的串行化:當一個對象串行化時,如果希望該對象的某些屬性不被儲存,可以通過在類定義中重寫readObject()和WriteObject()方法來實作。

串行化隻能儲存對象的非靜态成員變量(執行個體變量),而不能儲存任何成員方法和靜态成員變量,并且儲存的隻是變量的值,對于變量的任何修飾符都不能儲存。對于某些類型的對象,其狀态是瞬時的,這樣的對象是無法儲存其狀态的,如Thread對象或流對象。對于這樣的成員變量,必須用transient關鍵字标明,否則編譯器将報錯。任何用transient關鍵字标明的成員變量,都不會被儲存。另外,串行化可能涉及将對象存放到磁盤上或在網絡上發送資料,這時會産生安全問題。對于一些需要保密的資料,不應儲存在永久媒體中(或者不應簡單地不加處理地儲存下來),為了保證安全,應在這些變量前加上transient關鍵字。

⑥管道流

管道用來把一個程式、線程和代碼塊的輸出連接配接到另一個程式、線程和代碼塊的輸入。java.io中提供了類PipedInputStream和PipedOutputStream作為管道的輸入/輸出流。

管道輸入流作為一個通信管道的接收端,管道輸出流則作為發送端。管道流必須是輸入輸出流并用,即在使用管道前,兩者必須進行連接配接。

管道輸入/輸出流可以用兩種方式進行連接配接:

1)在構造方法中進行連接配接:PipedInputStream(PipedOutputStream pos);

PipedOutputStream(PipedInputStream pis);

2)通過各自的connect()方法連接配接:在類PipedInputStream中,connect(PipedOutputStream pos);

在類PipedOutputStream中,connect(PipedInputStream pis);

java清空inputstream中的流_Java 流處理

将資料從輸出管道進,從輸入管道出

⑦記憶體流

為了支援在記憶體上的I/O,java.io中提供了類ByteArrayInputStream、ByteArrayOutputStream、StringBufferInputStream、ByteArrayInputStream可以從指定的位元組數組中讀取資料。ByteArrayOutputStream中提供了緩沖區可以存放資料(緩沖區大小可以在構造方法中設定,預設為32),可以用write()方法向其中寫入資料,然後用toByteArray()方法将緩沖區中的有效位元組寫到位元組數組中去。size()方法可以知道寫入的位元組數,reset()可以丢棄所有内容。StringBufferInputStream與ByteArrayInputStream相類似,不同點在于它是從字元緩沖區StringBuffer中讀取16位的Unicode資料,而不是8位的位元組資料。(已被StringReader取代)

ByteArrayInputStream:

ByteArrayInputStream(byte[] buf)

ByteArrayInputStream(byte[] buf, int offset, int length)

ByteArrayOutputStream :

void reset() :重寫内容

int size() :傳回寫入的位元組數

byte[] toByteArray():以新配置設定的位元組數組形式傳回寫入的内容

StringtoString()  :以預設字元編碼方式把内容程式設計字元串傳回

String toString(String enc) :以指定字元編碼方式傳回字元串

void writeTo(OutputStream out) :把内容寫到另一個輸出流中

⑧順序輸入流

java.io中提供了類SequenceInputStream,使應用程式可以将幾個輸入流順序連接配接起來,讓程式員看起來就像是一個比較長的流一樣。順序輸入流提供了将多個不同的輸入流統一為一個輸入流的功能,這使得程式可能變得更加簡潔。如:FileInputStream f1,f2;     String s;     f1  = new FileInputStream(“file1.txt”);   f2  = new FileInputStream(“file2.txt”);     SequenceInputStream fs = new SequenceInputStream(f1, f2); DataInputStream ds = new DataInputStream(fs);    while((s = ds.readLine()) != null )   System.out.println(s);

3、字元流

java清空inputstream中的流_Java 流處理

以Reader和Writer為基礎派生的一系列類。也是抽象類,隻提供了一系列用于字元流處理的接口。它們的方法與類InputStream和OutputStream類似,隻不過其中的參數換成字元或字元數組。

——基類:Reader:

void close()

void mark(int readAheadLimit)

boolean markSupported():

int read()

int read(char[] cbuf)

int read(char[] cbuf, int off, int len)

boolean ready()

void reset()

long skip(long n)

——基類:Writer:

void close()

void flush()

void write(char[] cbuf)

void write(char[] cbuf, int off, int len)

void write(int c)

void write(String str)

void write(String str, int off, int len)

InputStreamReader和OutputStreamWriter是java.io包中用于處理字元流的最基本的類,用來在位元組流和字元流之間作為中介:從位元組輸入流讀入位元組,并按編碼規範轉換為字元;往位元組輸出流寫字元時先将字元按編碼規範轉換為位元組。使用這兩者進行字元處理時,在構造方法中應指定一定的平台規範,以便把以位元組方式表示的流轉換為特定平台上的字元表示。

InputStreamReader(InputStreamin);                       //預設規範

InputStreamReader(InputStreamin, String enc);       //指定規範enc

OutputStreamWriter(OutputStreamout);                   //預設規範

OutputStreamWriter(OutputStreamout, String enc);   //指定規範enc

如果讀取的字元流不是來自本地時(比如網上某處與本地編碼方式不同的機器),那麼在構造字元輸入流時就不能簡單地使用預設編碼規範,而應該指定一種統一的編碼規範“ISO 8859_1”,這是一種映射到ASCII碼的編碼方式,能夠在不同平台之間正确轉換字元。

InputStreamReader ir = new InputStreamReader( is, “8859_1” );

——緩存流:BufferedReader和BufferedWriter:

同樣的,為了提高字元流處理的效率,java.io中也提供了緩沖流BufferedReader和BufferedWriter。其構造方法與BufferedInputStream和BufferedOutputStream相類似。另外,除了read()和write()方法外,它還提供了整行字元處理方法:

public String readLine(): BufferedReader的方法,從輸入流中讀取一行字元,行結束标志為‘\n’、‘\r’或兩者一起。

public void newLine(): BufferedWriter的方法,向輸出流中寫入一個行結束标志,它不是簡單的換行符‘\n’或‘\r’,而是系統定義的行隔離标志

——其它字元流:

對字元數組進行處理:CharArrayReader、CharArrayWriter

對文本檔案進行處理:FileReader、FileWriter

對字元串進行處理:StringReader、StringWriter

過濾字元流:FilterReader、FilterWriter

管道字元流:PipedReader、PipedWriter

行處理字元流:LineNumberReader

列印字元流:PrintWriter

4、檔案操作/随機通路檔案

java清空inputstream中的流_Java 流處理

File:以檔案路徑名的形式代表一個檔案

FileDescriptor:代表一個打開檔案的檔案描述

FileFilter & FilenameFilter:用于列出滿足條件的檔案

File.list(FilenameFilter fnf)

File.listFiles(FileFilter ff)

FileDialog.setFilenameFilter(FilenameFilter fnf)

FileInputStream & FileReader:順序讀檔案

FileOutputStream & FileWriter:順序寫檔案

RandomAccessFile:提供對檔案的随機通路支援。

——檔案操作:File:

File(String pathname)

File f=new File(“c:\data\temp.dat”);

File f=new File(“data\ temp.dat”);

File f=new File(“temp.dat”);

File(String parent, String child)

File f=new File(“c:\data” ,“temp.dat”);

File f=new File(“data ” ,“ temp.dat”);

File(File parent, String child)

File f=new File(new File(“c:\data”) ,“temp.dat”);

File f=new File(new File(“data ”) ,“ temp.dat”);

boolean canRead()

boolean canWrite()

boolean setReadOnly()

boolean exists()

boolean isDirectory()

boolean isFile()

boolean isHidden()

long lastModified()

boolean setLastModified(long time)

long length()

String[] list()

String[] list(FilenameFilter filter)

File[] listFiles()

File[] listFiles(FileFilter filter)

File[] listFiles(FilenameFilter filter)

static File[] listRoots()

boolean mkdir()

boolean mkdirs()

boolean createNewFile()

static File createTempFile(String prefix, String suffix)

static File createTempFile(String prefix, String suffix, File directory)

boolean delete()

void deleteOnExit()

boolean renameTo(File dest)

String getName()

File getParentFile()

String getParent()

String getPath()

boolean isAbsolute()

File getAbsoluteFile()

String getAbsolutePath()

File getCanonicalFile()

StringgetCanonicalPath()

——檔案操作:FileDescriptor:

FileInputStream & FileOutputStream & RandomAccessFile

FileDescriptor getFD()

通過FileDescriptor構造輸入輸出流

FileInputStream(FileDescriptor fdObj)

FileOutputStream(FileDescriptor fdObj)

FileReader(FileDescriptor fd)

FileWriter(FileDescriptor fd)

例如:

FileInputStream fin = new FileInputStream(“file.txt”);

FileReader fr = new FileReader(fin.getFD());

——随機通路檔案( RandomAccessFile )

對于FileInputStream/FileOutputStream、FileReader/FileWriter來說,它們的執行個體都是順序通路流,即隻能進行順序讀/寫。而類RandomAccessFile則允許對檔案内容同時完成讀和寫操作,它直接繼承object,并且同時實作了接口DataInput和DataOutput,提供了支援随機檔案操作的方法:

readXXX()或writeXXX():如ReadInt(), ReadLine(), WriteChar(), WriteDouble()等。

int skipBytes(int n):将指針鄉下移動若幹位元組

length():傳回檔案長度

long getFilePointer():傳回指針目前位置

void seek(long pos):将指針調到所需位置

在生成一個随機檔案對象時,除了要指明檔案對象和檔案名之外,還需要指明通路檔案的模式。

RandomAccessFile(File file, String mode)

RandomAccessFile(Stringname, String mode)

mode 的取值:

“r” 隻讀. 任何寫操作都将抛出IOException。

“rw” 讀寫. 檔案不存在時會建立該檔案,檔案存在時,原檔案内容不變,通過寫操作改變檔案内容。

“rws” 同步讀寫. 等同于讀寫,但是任何寫操作的内容都被直接寫入實體檔案,包括檔案内容和檔案屬性。

“rwd” 資料同步讀寫. 等同于讀寫,但任何内容寫操作都直接寫到實體檔案,但對檔案屬性内容的修改不是這樣。

例:File f = new File(“file.txt”);

new RandomAccessFile(f, “r”);

new RandomAccessFile(f, “rw”);

new RandomAccessFile(“file1.txt”, “r”);

new RandomAccessFile(“file2.txt”, “rw”);

java清空inputstream中的流_Java 流處理
java清空inputstream中的流_Java 流處理