国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java I/O簡介

darkbug / 2277人閱讀

摘要:如果不指定字符集,則使用系統默認字符編碼,系統的默認字符編碼一般是。所以更準確的說,是將一個字節輸入流按照給定的字符編碼來解碼,從而得到一個字符輸入流。當然,缺點就是不能選擇使用的字符編碼。

相對于PythonC來說,Java的I/O操作API比較復雜,因此本文打算做個簡單的介紹。

1. I/O分類

總的來說Java的I/O按照處理數據的粒度和方向來劃分,一共可以分為4類:

基于字節

輸入 InputStream

輸出 OutputStream

基于字符

輸入 Reader

輸出 Writer

使用原則:要讀寫二進制數據時,使用基于字節的API;要讀寫文本數據時,使用基于字符的API,文本數據操作需要指定字符編碼。強調一點,本文說的字符是指Java的數據類型char類型,并不是C語言中的char類型(該類型長度為8位,一個字節),即Java中的一個字符有可能包含多個字節。

這里提到的InputStream, OutputStream, ReaderWriter 是Java API里的4個抽象類,不能用來初始化新的實例,我們只能從這4個類的子類(或者后代類)來創建I/O操作的實例,而且正是這些子類實現類不同介質和不同功能的I/O。另外,兩個用于輸入的抽象類都定義了一個抽象的int read()方法,兩個用于輸出的抽象類都定義了一個抽象的void write()方法,這些抽象方法則由子類來實現。

2. 文件I/O的使用

Java I/O可以可以應用于各種輸入輸出介質,包括文件、控制臺(也是文件的一種)、內存、網絡等。這里先介紹文件I/O,搞懂了文件I/O相關的API后,其他的I/O就都好理解了。

最基本方法

根據第一節的分類,文件I/O的API也分為基于字節基于字符 的兩大類。我們先來看最基礎的文件I/O的類:

基于字節

FileInputStream
該類的read()方法每次從文件讀取一個字節。

FileOutputStream
該類的write()方法每次向文件寫入一個字節。

基于字符

InputStreamReader
該類的read()方法每次從一個輸入流中讀取一個字符。該類的構造函數的第一個參數是一個InputStream實例,也就是將說該類將一個基于字節的輸入流變成一個基于字符的輸入流。如果不指定字符集,則使用系統默認字符編碼,Ubuntu系統的默認字符編碼一般是UTF-8。所以更準確的說,是將一個字節輸入流按照給定的字符編碼來解碼,從而得到一個字符輸入流。

OutputStreamWriter
該類的write()方法每次向一個輸出流中寫入一個字符。該類的構造函數的第一個參數是一個OutputStream實例,也就是說該類將一個基于字節的輸出流變成一個基于字符的輸出流。如果不指定字符集,則使用系統默認字符編碼,Ubuntu系統的默認字符編碼一般是UTF-8。所以更準確的說,是將一個字節輸出流按照給定的字符編碼來編碼(把要輸出的字符轉換成二進制數據),從而得到一個字符輸出流。

FileReader
該類的read()方法每次從文件讀取一個字符。這個類的作用等于如下代碼:

InputStreamReader in = new InputStreamReader(new FileInputStream(pathToFile));
也就是先從一個文件創建一個字節輸入流,然后再采用系統默認編碼方式轉換成一個字符輸入流。當然,缺點就是不能選擇使用的字符編碼。

FileWriter
該類的write()方法每次向文件寫入一個字符。這個類的作用等于如下代碼:

`OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(pathToFile));
具體解釋和FileReader類似。

介紹完常用類,我們來講下如何使用。

二進制數據讀寫(基于字節)

如果要從文件讀入二進制數據,則先構造一個FileInputStream實例,然后調用read()方法每次讀入一個字節,也可以調用read方法的其他實現,每次讀入多個字節。

如果要向文件寫入二進制數據,則先構造一個FileOutputStream示例,然后調用write()方法每次寫入一個字節,也可以調用write方法的其他實現,每次寫入多個字節。

文本數據讀寫(基于字符)

如果要從文件讀入文本數據,可以選擇如下兩種方式:

構造一個FileReader實例,使用系統默認編碼,然后調用read()方法每次讀入一個字符,也可以調用read方法的其他實現,每次讀入多個字符。

采用如下方式構造一個InputStreamReader實例:new InputStreamReader(new FileInputStream(pathToFile), codecName),使用指定的字符編碼,然后調用read()方法每次讀入一個字符,也可以調用read方法的其他實現,每次讀入多個字符。

如果要向文件寫入文本數據,可以選擇如下兩種方式:

構造一個FileWriter實例,使用系統默認編碼,然后調用write()方法每次寫入一個字符,也可以調用write方法的其他實現,每次寫入多個字符。

采用如下方式構造一個OutputStreamwriter實例:new OutputStreamWriter(new FileOutputStream(pathToFile), codecName),使用指定的字符編碼,然后調用write()方法每次寫入一個字符,也可以調用write方法的其他實現,每次寫入多個字符。

來看下代碼實例,文件~/tmp/words中存放了一行中文字符,采用的是UTF-8編碼方式:

~/tmp/words 
你好

下面的代碼展示了基于字節和基于字符兩種方式讀取文件內容的區別:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Hello {

  public static void main(String[] args) {
    String wordFileName = "~/tmp/words";
    String wordFilePath = wordFileName.replace("~", System.getProperty("user.home"));

    try {
      // byte-based input
      System.out.println("InputStream");
      FileInputStream fin = new FileInputStream(wordFilePath);
      int c;
      while ((c = fin.read()) != -1) {
        System.out.printf("%02x ", c);
      }
      System.out.println();

      // char-based input
      System.out.println("Reader");
      InputStreamReader rin = new InputStreamReader(
          new FileInputStream(wordFilePath), "UTF-8");
      while ((c = rin.read()) != -1) {
        System.out.printf("%02x ", c);
      }
      System.out.println();
    } catch (IOException e) {
      System.out.println(e);
      System.exit(1);
    }
  }
}

運行結果為:

InputStream
e4 bd a0 e5 a5 bd 0a 
Reader
4f60 597d 0a 

可以看出,基于字節的輸入每次讀入一個字節,兩個漢字一共6個字節,換行符一個字節(0x0a),一共讀了7次。而基于字符的輸入每次讀入后保存的結果為兩個字節(因為Java內部都是UTF-16表示的,因此從文件讀入字符的時候已經做了UTF-8到UTF-16轉換),兩個漢字和一個換行符一共讀了三次。

更方便的方法

上一小節說的方法其實相當于C語言中的中的如下函數:

FileInputStream: read, fgetc, fread等

FileOutputStream: write, fputc, fwrite等

InputStreamReader, FileReader: 如果文件不是ASCII編碼的,則相當于fgetwc(wchar.h文件中定義)等;如果文件是ASCII編碼,則相當于fgetc等。

OutputStreamWriter, FileWriter: 同上,相當于fputwc和fputc等。

這些只能基于單個字符或者單個字節進行輸入輸出的API使用起來比較麻煩,比較使用用來操作二進制數據。本節會介紹一些更方便的文件I/O方法。

讀寫二進制文件

在不考慮對象序列化等更復雜的方法時,Java也提供了DataInputStreamDataOutputStream 的類,用來從二進制流中讀取Java的基本類型數據或者向二進制流中寫入基本類型數據,比如讀一個整型和寫入一個整型。

DataInputStream是FilterInputStream的子類,DataOutputStream則是FilterOutputStream的子類,都屬于過濾類的流,其作用是從一個流讀入數據,然后轉換一下表達方式在輸出,比如DataInputStream可以從FileInputStream連續讀出4個字節,然后轉換成一個整型返回給調用者。

讀寫二進制文件更高級的就是各種對象序列化方法了,這個本文不討論。

讀寫文本文件

讀寫文本文件我們很習慣于按照行來進行讀寫,比如C語言的scanfprintf 函數。在Java中分別使用下面兩個類來進行:

Scanner: 有眾多構造函數,其中一個可以從指定輸入流,然后實現類似scanf函數的效果。

PrintWritter: 該類在一個Writer的基礎上實現了常用的print, println和printf接口。

如下代碼從一個文件構造一個Scanner實例,然后你就可以調用Scanner類的next, nextInt, nextLine的函數來從文件讀取輸入:

Scanner in = new Scanner(new FileInputStream(pathToFile));

Scanner類還有其他構造函數,能夠指定字符編碼,以及從其他類型的參數構造出一個實例。

如下代碼從一個文件構造出一個PrintWriter實例,然后你就可以調用print, println和printf了:

PrintWriter out = new PrintWriter(new FileWriter(pathToFile));

不過還有個更方便的構造函數:

PrintWriter out = new PrintWriter(pathToFile);
3. 標準輸入,標準輸出和標準錯誤

System類的三個成員in, out, err分別系統的標準輸入、標準輸出和標準錯誤,通過查看源碼可以發現他們的定義是這樣的:

public final class System {
  ...
  public static final InputStream in = null;
  public static final PrintStream out = null;
  public static final PrintStream err = null;
  ...
}

因此要從標準輸出讀取數據的化,可以直接使用InputStream的read方法,或者構造一個Scanner實例來使用:

System.in.read();
Scanner in = new Scanner(System.in);

標準輸出和標準錯誤則是兩個PrintStream類的實例,查看代碼可以發現,這個類的實現基本上和PrintWriter一樣,也就是說可以直接使用print, println和printf等方法進行數據輸出。還有,PrintStream類是繼承自FilterOutputStream,因此write方法也是可用的。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64168.html

相關文章

  • JAVA NIO.1

    摘要:特點面向塊的傳統是面向流的。有四個基本屬性容量,能夠容納的最大元素數目,在創建時設定并不能更改中有效位置數目,不能對超過中的區域進行讀寫。與緩沖區不同,通道主要由接口指定。方法獲取支持的所有字符集獲取實例編解碼文件鎖進程級支持文件鎖定功能。 簡介 NIO的所有類都被放在java.nio包或其子包下。 特點 面向塊的I/O:傳統JavaIO是面向流的I/O。流I/O一次處理一個字節。N...

    Steve_Wang_ 評論0 收藏0
  • 高并發 - 收藏集 - 掘金

    摘要:在中一般來說通過來創建所需要的線程池,如高并發原理初探后端掘金閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。 AbstractQueuedSynchronizer 超詳細原理解析 - 后端 - 掘金今天我們來研究學習一下AbstractQueuedSynchronizer類的相關原理,java.util.concurrent包中很多類都依賴于這個類所提供的隊列式...

    levius 評論0 收藏0
  • 高并發 - 收藏集 - 掘金

    摘要:在中一般來說通過來創建所需要的線程池,如高并發原理初探后端掘金閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。 AbstractQueuedSynchronizer 超詳細原理解析 - 后端 - 掘金今天我們來研究學習一下AbstractQueuedSynchronizer類的相關原理,java.util.concurrent包中很多類都依賴于這個類所提供的隊列式...

    fantix 評論0 收藏0
  • 通用文件服務組件(Netty實現版本)

    摘要:操作指引該文件服務組件的使用需要分為兩個部分,一個是服務端配置與啟動,一個是客戶端的配置與啟動。在調用文件服務返回的路徑的時候,需要用到服務端訪問文件的地址,進而訪問相應的文件內容。 本文所述文件服務組件在筆者此前一篇文章中已有闡述(基于netty的文件上傳下載組件),不過本文將基于之前這個實現再次進行升級改造,利用基于注解的方式進行自動裝配。 1. 簡介 1.1 Netty簡介 Ne...

    fou7 評論0 收藏0
  • java中的NIO

    摘要:緩沖區一個對象是固定數量的數據的容器。緩沖區的工作與通道緊密聯系。對于操作而言,從通道讀取的數據會按順序被散布稱為到多個緩沖區,將每個緩沖區填滿直至通道中的數據或者緩沖區的最大空間被消耗完。文件通道總是阻塞式的,因此不能被置于非阻塞模式。 簡介 從JDK1.4開始,java中提供一個種叫NIO(Non-Blocking IO)的IO處理機制。與以往的標準IO機制(BIO,Blockin...

    crossoverJie 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<