c++二进制文件java读取int_吃透Java基础十二:IO
一、什么是IO流
Java中將輸入輸出抽象稱為流,就好像水管,將兩個容器連接起來。流是一組有順序的,有起點和終點的字節集合,是對數據傳輸的總稱或抽象。即數據在兩設備間的傳輸稱為流。
按數據來源(去向)分類:
- 文件:FileInputStream、FileOutputStream、FileReader、FileWriter
- 數組:字節數組(byte[]):ByteArrayInputStream、ByteArrayOutputStream
- 字符數組(char[]):CharArrayReader、CharArrayWriter
- 管道操作:PipedInputStream、PipedOutputStream、PipedReader、PipedWriter
- 基本數據類型:DataInputStream、DataOutputStream
- 緩沖操作:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
- 對象序列化反序列化:ObjectInputStream、ObjectOutputStream
- 打印:PrintStream、PrintWriter
- 轉換:InputStreamReader、OutputStreWriter
根據處理數據類型不同分類
- 字節流:數據流中最小的數據單元是字節。
- 字符流:數據流中最小的數據單元是字符, Java中的字符是Unicode編碼,一個字符占用兩個字節。
字節流讀取單個字節,字符流讀取單個字符,字節流用來處理二進制文件如:圖片、MP3、視頻文件等等,字符流用來處理文本文件,可以看做是特殊的二進制文件,使用了某種編碼,人可以閱讀。
根據數據流向不同分類
- 輸入流: 程序從輸入流讀取數據源。數據源包括外界(鍵盤、文件、網絡…),即是將數據源讀入到程序的通信通道
- 輸出流:程序向輸出流寫入數據。將程序中的數據輸出到外界(顯示器、打印機、文件、網絡…)的通信通道。
二、源碼分析
IO 類雖然很多,但最基本的是 4 個抽象類:InputStream、OutputStream、Reader、Writer。最基本的方法也就是一個讀 read() 方法、一個寫 write() 方法。方法具體的實現還是要看繼承這 4 個抽象類的子類,畢竟我們平時使用的也是子類對象。
字節輸入流:InputStream
public abstract class InputStream implements Closeable { //讀取一個字節數據,并返回讀到的數據,如果返回-1,表示讀到了輸入流的末尾。 public abstract int read() throws IOException; //將數據讀入一個字節數組,同時返回實際讀取的字節數。如果返回-1,表示讀到了輸入流的末尾。 public int read(byte b[]) throws IOException { return read(b, 0, b.length); } //將數據讀入一個字節數組,同時返回實際讀取的字節數。如果返回-1,表示讀到了輸入流的末尾。 //off指定在數組b中存放數據的起始偏移位置;len指定讀取的最大字節數。 public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = read(); if (c == -1) { return -1; } b[off] = (byte)c; int i = 1; try { for (; i < len ; i++) { c = read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; } //在輸入流中跳過n個字節,并返回實際跳過的字節數。 public long skip(long n) throws IOException { long remaining = n; int nr; if (n <= 0) { return 0; } int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining); byte[] skipBuffer = new byte[size]; while (remaining > 0) { nr = read(skipBuffer, 0, (int)Math.min(size, remaining)); if (nr < 0) { break; } remaining -= nr; } return n - remaining; } //返回在不發生阻塞的情況下,可讀取的字節數。 public int available() throws IOException { return 0; } //關閉輸入流,釋放和這個流相關的系統資源。 public void close() throws IOException {} //標記讀取位置,下次還可以從這里開始讀取,使用前要看當前流是否支持, //可以使用 markSupport() 方法判斷 public synchronized void mark(int readlimit) {} //返回到上一個標記。 public synchronized void reset() throws IOException { throw new IOException("mark/reset not supported"); } //測試當前流是否支持mark和reset方法。如果支持,返回true,否則返回false。 public boolean markSupported() { return false; }}字節輸出流:OutputStream
public abstract class OutputStream implements Closeable, Flushable { //往輸出流中寫入一個字節。 public abstract void write(int b) throws IOException; //往輸出流中寫入數組b中的所有字節。 public void write(byte b[]) throws IOException { write(b, 0, b.length); } //往輸出流中寫入數組b中從偏移量off開始的len個字節的數據。 public void write(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } for (int i = 0 ; i < len ; i++) { write(b[off + i]); } } //強制刷新,將緩沖中的數據寫入 public void flush() throws IOException { } //關閉輸出流,釋放和這個流相關的系統資源。 public void close() throws IOException { }}```**字符輸入流Reader**```javapublic abstract class Reader implements Readable, Closeable { //讀取字符到字符緩存中 public int read(java.nio.CharBuffer target) throws IOException { int len = target.remaining(); char[] cbuf = new char[len]; int n = read(cbuf, 0, len); if (n > 0) target.put(cbuf, 0, n); return n; } //讀取一個字符,返回值為讀取的字符 public int read() throws IOException { char cb[] = new char[1]; if (read(cb, 0, 1) == -1) return -1; else return cb[0]; } //讀取一系列字符到數組cbuf[]中,返回值為實際讀取的字符的數量 public int read(char cbuf[]) throws IOException { return read(cbuf, 0, cbuf.length); } //讀取len個字符,從數組cbuf[]的下標off處開始存放,返回值為實際讀取的字符數量,該方法必須由子類實現 abstract public int read(char cbuf[], int off, int len) throws IOException; //跳過指定長度的字符數量 public long skip(long n) throws IOException { if (n < 0L) throw new IllegalArgumentException("skip value is negative"); int nn = (int) Math.min(n, maxSkipBufferSize); synchronized (lock) { if ((skipBuffer == null) || (skipBuffer.length < nn)) skipBuffer = new char[nn]; long r = n; while (r > 0) { int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); if (nc == -1) break; r -= nc; } return n - r; } } //告訴此流是否已準備好被讀取。 public boolean ready() throws IOException { return false; } //判斷當前流是否支持標記流 public boolean markSupported() { return false; } //標記讀取位置,下次還可以從這里開始讀取,使用前要看當前流是否支持, //可以使用 markSupport() 方法判斷 public void mark(int readAheadLimit) throws IOException { throw new IOException("mark() not supported"); } //返回到上一個標記。 public void reset() throws IOException { throw new IOException("reset() not supported"); } //關閉輸入流,釋放和這個流相關的系統資源。 abstract public void close() throws IOException;}字符輸出流Writer
public abstract class Writer implements Appendable, Closeable, Flushable { //將整型值c的低16位寫入輸出流 public void write(int c) throws IOException { synchronized (lock) { if (writeBuffer == null){ writeBuffer = new char[WRITE_BUFFER_SIZE]; } writeBuffer[0] = (char) c; write(writeBuffer, 0, 1); } } //將字符數組cbuf[]寫入輸出流 public void write(char cbuf[]) throws IOException { write(cbuf, 0, cbuf.length); } //將字符數組cbuf[]中的從索引為off的位置處開始的len個字符寫入輸出流 abstract public void write(char cbuf[], int off, int len) throws IOException; //將字符串str中的字符寫入輸出流 public void write(String str) throws IOException { write(str, 0, str.length()); } //將字符串str 中從索引off開始處的len個字符寫入輸出流 public void write(String str, int off, int len) throws IOException { synchronized (lock) { char cbuf[]; if (len <= WRITE_BUFFER_SIZE) { if (writeBuffer == null) { writeBuffer = new char[WRITE_BUFFER_SIZE]; } cbuf = writeBuffer; } else { // Don't permanently allocate very large buffers. cbuf = new char[len]; } str.getChars(off, (off + len), cbuf, 0); write(cbuf, 0, len); } } //追加寫入一個字符序列 public Writer append(CharSequence csq) throws IOException { if (csq == null) write("null"); else write(csq.toString()); return this; } //追加寫入一個字符序列的一部分,從 start 位置開始,end 位置結束 public Writer append(CharSequence csq, int start, int end) throws IOException { CharSequence cs = (csq == null ? "null" : csq); write(cs.subSequence(start, end).toString()); return this; } //追加寫入一個 16 位的字符 public Writer append(char c) throws IOException { write(c); return this; } //強制刷新,將緩沖中的數據寫入 abstract public void flush() throws IOException; //關閉輸出流,流被關閉后就不能再輸出數據了 abstract public void close() throws IOException;}三、運用場景
1、字節流與字符流的轉換
- InputStreamReader:將一個字節流中的字節解碼成字符。
- OutputStreamWriter:將寫入的字符編碼成字節后寫入一個字節流。
字節流和字符流轉換看一下例子就行了:
1. 創建一個文本文件:bobo.txt,然后寫入內容:波波。
2. 用FileInputStream讀出文本內容然后以字節數組的形式緩存在fileInputStream里面。
3. 用InputStreamReader 把fileInputStream緩存的字節數組讀取到定義的charArray的字符數組里面,并且輸出。
4. 用OutputStreamWriter把字符數組charArray里面的字符寫到InputStreamReader的字節數組緩存起來,然后輸出。
5. 輸出結果如下圖所示。
運行輸出:
2、字節數組的輸入輸出
ByteArrayOutputStream :字節數組輸出流在內存中創建一個字節數組緩沖區,所有發送到輸出流的數據保存在該字節數組緩沖區中。
ByteArrayInputStream :字節數組輸入流在內存中創建一個字節數組緩沖區,從輸入流讀取的數據保存在該字節數組緩沖區中。
輸出:
[1, 2, 3]3、對象的輸入輸出
java.io.ObjectOutputStream是實現序列化的關鍵類,它可以將一個對象轉換成二進制流通過write()方法寫入到OutputStream輸出流中。然后可以通過ObjectInputStream的read()方法將對應的InputStream二進制流還原成對象。
輸出
falselist:[1, 2, 3] list1:[1, 2, 3]4、控制臺的輸入輸出
- System.out:標準的輸出流,out是System類里面的靜態變量,其類型是PrintStream,PrintStream繼承于FilterOutputStream,也是輸出類OutputStream的子類。
- System.in:標準的輸入流,in是System類里面的靜態變量,其類型是
InputStream。
我們常用的System.out和System.in作為控制臺的輸出與輸入。
單個字符輸入
整行字符輸入:
運行輸出:
請輸入一行字符:bobo輸入的內容為:bobo5、二進制文件的輸入輸出
輸出:
6、文本文件的輸入輸出
用FileWriter和FileReader讀取文本文件:
輸出:
使用字節流和字符流的轉換類 InputStreamReader 和 OutputStreamWriter 可以指定文件的編碼,使用 Buffer 相關的類來讀取文件的每一行。
運行輸出:
編碼方式為:GBK波波測試文件的讀寫總結
以上是生活随笔為你收集整理的c++二进制文件java读取int_吃透Java基础十二:IO的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wsl使用可视化界面_通过 VcXsrv
- 下一篇: html中获取modelandview中