java io 字節流InputStream詳解

程序員cow哥 發佈 2022-11-28T14:48:05.707040+00:00

概述InputStream 為字節輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示字節輸入流的所有類的超類。

概述

InputStream 為字節輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示字節輸入流的所有類的超類。 繼承自InputStream 流是向程序中輸入數據的,且數據單位為字節(8bit);

InputStream是輸入字節數據用的類,所以InputStream類提供了3種重載的read方法.Inputstream類中的常用方法:

  (1) public abstract int read( ):讀取一個byte的數據,返回值是高位補0的int類型值。若返回值=-1說明沒有讀取到任何字節讀取工作結束。

  (2) public int read(byte b[ ]):讀取b.length個字節的數據放到b數組中。返回值是讀取的字節數。該方法實際上是調用下一個方法實現的

  (3) public int read(byte b[ ], int off, int len):從輸入流中最多讀取len個字節的數據,存放到偏移量為off的b數組中。

  (4) public int available( ):返回輸入流中可以讀取的字節數。注意:若輸入阻塞,當前線程將被掛起,如果InputStream對象調用這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類對象調用才有用。

  (5) public long skip(long n):忽略輸入流中的n個字節,返回值是實際忽略的字節數, 跳過一些字節來讀取。

  (6) public int close( ) :我們在使用完後,必須對我們打開的流關閉。

主要的子類:

1) FileInputStream把一個文件作為InputStream,實現對文件的讀取操作

2) ByteArrayInputStream:把內存中的一個緩衝區作為InputStream使用

3) StringBufferInputStream:把一個String對象作為InputStream

4) PipedInputStream:實現了pipe的概念,主要在線程中使用

5) SequenceInputStream:把多個InputStream合併為一個InputStream

6) FilterInputStream :用來「封裝其它的輸入流,並為它們提供額外的功能」。它的常用的子類有BufferedInputStream和DataInputStream。

BufferedInputStream的作用就是為「輸入流提供緩衝功能,以及mark()和reset()功能」。

DataInputStream 是用來裝飾其它輸入流,它「允許應用程式以與機器無關方式從底層輸入流中讀取基本 Java 數據類型」。應用程式可以使用DataOutputStream(數據輸出流)寫入由DataInputStream(數據輸入流)讀取的數據。

FileInputStream 子類

FileInputStream是Java語言中抽象類InputStream用來具體實現類的創建對象。FileInputStream可以從文件系統中的某個文件中獲得輸入字節,獲取的文件可用性取決於主機環境,提供的主要方法:

int available()

返回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀取(或跳過)的估計剩餘字節數。

void close()

關閉此文件輸入流並釋放與此流有關的所有系統資源。

protected void finalize()

確保在不再引用文件輸入流時調用其 close 方法。

FileChannel getChannel()

返回與此文件輸入流有關的唯一 FileChannel 對象。

FileDescriptor getFD()

返回表示到文件系統中實際文件的連接的 FileDescriptor 對象,該文件系統正被此 FileInputStream 使用。

int read()

從此輸入流中讀取一個數據字節。

int read(byte[] b)

從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。

int read(Byte[] b, int off, int len)

從此輸入流中將最多 len 個字節的數據讀入一個 byte 數組中。

long skip(long n)

從輸入流中跳過並丟棄 n 個字節的數據。

利用FileInputStream進行文件複製

public class FileInputStreamcopy {

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

//1. 創建字節輸入流對象,用來讀取

FileInputStream fis = new FileInputStream("E:\\test.txt");

//2創建字節輸出流對象,用來寫入//沒有會創建

FileOutputStream fs = new FileOutputStream(E:\\copy.txt);

//3創建一個數組用來讀取

byte arr[] = new byte[1024 * 8];

int len;//用來計數

while ((len = fis.read(arr)) != -1) {

//從文件中用字節數組讀取數組,存儲到字節數組中

// 每讀取到一個內容,就把讀取到的內容寫入到目的地文件

fs.write(arr,0,len);

}

//釋放資源

fs.close();

fis.close();

}

}

ByteArrayInputStream 子類

ByteArrayInputStream 是字節數組輸入流。它繼承於InputStream。

它包含一個內部緩衝區,該緩衝區包含從流中讀取的字節;通俗點說,它的內部緩衝區就是一個字節數組,而ByteArrayInputStream本質就是通過字節數組來實現的。

public void reset() 將此字節數組輸出流的 count 欄位重置為零,從而丟棄輸出流中目前已累積的所有數據輸出。

public byte[] toByteArray() 創建一個新分配的字節數組。數組的大小和當前輸出流的大小,內容是當前輸出流的拷貝。

public String toString() 將緩衝區的內容轉換為字符串,根據平台的默認字符編碼將字節轉換成字符。

public void write(int w) 將指定的字節寫入此字節數組輸出流。

public void write(byte []b, int off, int len) 將指定字節數組中從偏移量 off 開始的 len 個字節寫入此字節數組輸出流。

public void writeTo(OutputStream outSt) 將此字節數組輸出流的全部內容寫入到指定的輸出流參數中。

使用例子代碼:

public class ByteArrayInputStreamTest{

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

ByteArrayOutputStream out = new ByteArrayOutputStream();

//字節值被放入內部數組

out.write("abc中文".getBytes());

out.close();

byte[] a = out.toByteArray();

System.out.println(Arrays.toString(a));

InputStreamReader in = new InputStreamReader(

new ByteArrayInputStream(a));

int c;

while ((c = in.read()) != -1) {

System.out.println((char) c);

}

in.close();

}

}

PipedInputStream 子類

PipedInputStream類管道輸入流,它是可以連接管道輸出流,管道輸入流提供了要寫入管道輸出流的所有數據的字節。

PipedInputStream類方法有:

int read():讀取數據的下一個字節。

int read(byte []b,int off,int len):讀取len個字節數據到一個字節數組,off參數表示偏移量,len表示讀取數據的長度。

void receive(int b):接受一個字節的數據。

void connect(PipedOutputStream src):表示管道輸入流連接到管道輸出流src

int available():表示沒有什麼阻礙從輸入流中讀取字節數。

void close():表示關閉流。

例子代碼:

public class PipedInputStreamTest  { 
public static void main(String[] args) throws Exception { 
//創建PipedInputStream對象 
final PipedInputStream in=new PipedInputStream(); 
final PipedOutputStream out=new PipedOutputStream(); 
//兩個類進行連接 
in.connect(out); 
new Thread(new Runnable(){ 
        public void run(){ 
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
            //通過鍵盤讀取數據寫入管道流 
            PrintStream ps=new PrintStream(out); 
            System.out.print(Thread.currentThread().getName()+"請輸入內容:"); 
            try { 
                ps.println(br.readLine()); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
},"發送數據的線程").start(); 
new Thread(new Runnable(){ 
        public void run(){ 
            BufferedReader br=new BufferedReader(new InputStreamReader(in)); 
            try { 
                System.out.println(Thread.currentThread().getName()+"收到的內容:"+br.readLine()); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
},"接受數據的線程").start(); 
  } 
} 

FilterInputStream 子類

FilterInputStream 的作用是用來「封裝其它的輸入流,並為它們提供額外的功能」。它的常用的子類有BufferedInputStream和DataInputStream。
BufferedInputStream的作用就是為「輸入流提供緩衝功能,以及mark()和reset()功能」。
DataInputStream 是用來裝飾其它輸入流,它「允許應用程式以與機器無關方式從底層輸入流中讀取基本 Java 數據類型」。應用程式可以使用DataOutputStream(數據輸出流)寫入由DataInputStream(數據輸入流)讀取的數據。

提供的常法方法:

int available()

此方法返回可以從此輸入流中讀取(或跳過)的字節數的估計值,而不會被此輸入流的方法的下一個調用方阻塞。

void close()

此方法關閉此輸入流並釋放與該流關聯的所有系統資源。

void mark(int readlimit)

此方法標記此輸入流中的當前位置。

boolean markSupported()

此方法測試此輸入流是否支持標記和重置方法。

int read()

此方法從此輸入流中讀取下一個數據字節。

int read(byte [] b)

此方法將此輸入流中的byte.length字節數據讀入字節數組。

int read(byte [] b,int off,int len)

此方法將此輸入流中最多len個字節的數據讀入一個字節數組。

void reset()

此方法將此流重新定位到上次在此輸入流上調用mark方法時的位置。

long skip(long n)

此方法跳過並從此輸入流中丟棄n個字節的數據。

例子代碼:

public class FilterInputStreamDemo {

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

InputStream is = null;

FilterInputStream fis = null;

boolean bool = false;

try{

is = new FileInputStream("E:\\test.txt");

fis = new BufferedInputStream(is);

bool = fis.markSupported();

System.out.print("返回值: "+bool);

} catch(IOException e){

e.printStackTrace();

} finally {

if (is!=null)

is.close();

if(fis!=null)

fis.close();

}

}

}

SequenceInputStream子類

SequenceInputStream 可以將兩個或多個其他 InputStream 合併為一個。 首先,SequenceInputStream 將讀取第一個 InputStream 中的所有字節,然後讀取第二個 InputStream 中的所有字節。 這就是它被稱為 SequenceInputStream 的原因,因為 InputStream 實例是按順序讀取的。

構造方法

SequenceInputStream(InputStream s1, InputStream s2): 通過兩個參數初始化新創建的 SequenceInputStream(將按順序讀取這兩個參數,先讀取 s1,然後讀取 s2)

SequenceInputStream(Enumeration extends InputStream> e): 通過枚舉對象來初始化新創建的 SequenceInputStream,該參數必須是生成運行時類型為 InputStream 對象的 Enumeration 型參數。

例子代碼:

public class SequenceInputStreamTest {

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

InputStream s1 = new FileInputStream("E:\\text1.txt");

InputStream s2 = new FileInputStream("E:\\text1.txt");

SequenceInputStream sis = new SequenceInputStream(s1, s2);

InputStreamReader isr = new InputStreamReader(sis);

BufferedReader br = new BufferedReader(isr);

BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\text3.txt"));

String line = null;

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

bw.write(line);

bw.newLine();

bw.flush();

}

s1.close();

s2.close();

br.close();

bw.close();

}

}

關鍵字: