Iostream

iostream是C++中用於數據的流式輸入與輸出的頭文件，屬於C++標準程式庫的一部分。

iostream 為 Input/Output Stream 的縮寫，即是輸入/輸出流。「流」是一連串從I/O設備讀寫的字符。

## 概述

流輸入輸出庫中的大部分類都是模板類，可以適用於不同的字符類型或操作函數（如字符比較）。常用的一些字符類型的流輸入輸出已經用typedef定義了相應的模板特化實例。

例如，`basic_fstream<CharT,Traits>`是文件流輸入輸出的實現的模板類。它的一個特化實例：`fstream`是`basic_fstream<char,char_traits<char>>`的類型別名，換句話說，這是`basic_fstream`的字符類型為`char`使用默認字符操作集的特化實例。

流輸入輸出庫中的類可分為兩類。一是定義了界面的抽象，適用於任何流類型，無論是文件流、記憶體緩存區流或者網路socket流。二是對具體數據源與數據匯（sink）的流的實現。C++標準庫僅實現了文件流與記憶體緩衝區流。

流輸入輸出庫中的類依據是否實現底層或高層操作可分為兩類。實現了底層操作的類稱作流緩衝區（stream buffer），處理沒有任何格式化功能的字符。這些類極少被編程者直接使用。實現高層操作的類稱作流，並提供了不同的格式化能力，是構建於流緩衝區之上的。

下表列出了流輸入輸出庫的所有類的分類：

Class｜解釋｜Typedefs

Stream buffers (底層功能)

`[http://en.cppreference.com/w/cpp/io/basic_streambuf basic_streambuf]`｜提供了底層的輸入輸出界面，被具體的數據源與匯實現。罕用｜、`streambuf` - 字符類型`char`、`wstreambuf` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_filebuf basic_filebuf]`｜提供了文件流的底層的輸入輸出界面，被具體的數據源與匯實現。罕用｜、`filebuf` - 字符類型 `char`、`wfilebuf` -字符類型 `wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_stringbuf basic_stringbuf]`｜提供了字符文件流的底層的輸入輸出界面，被具體的數據源與匯實現。罕用｜、`stringbuf` - 字符類型`char`、`wstringbuf` - 字符類型`wchar_t`

Support classes

`[http://en.cppreference.com/w/cpp/io/ios_base ios_base]`｜管理格式化資訊與異常狀態｜不適用

`[http://en.cppreference.com/w/cpp/io/basic_ios basic_ios]`｜管理流緩衝區｜、`ios` - 字符類型`char`、`wios` - 字符類型`wchar_t`

Input streams buffers (高層功能)

`[http://en.cppreference.com/w/cpp/io/basic_istream basic_istream]`｜包裝一個抽象流緩衝區並提供高層輸入界面，如格式化能力｜、`istream` - 字符類型 `char`、`wistream` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_ifstream basic_ifstream]`｜包裝一個文件流緩衝區並提供高層輸入界面，如打開關閉流｜、`ifstream` - 字符類型`char`、`wifstream` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_istringstream basic_istringstream]`｜包裝一個字串流緩衝區並提供高層輸入界面，如訪問基礎字串｜、`istringstream` - 字符類型`char`、`wistringstream` - 字符類型`wchar_t`

Output streams buffers (高層功能)

`[http://en.cppreference.com/w/cpp/io/basic_ostream basic_ostream]`｜包裝一個抽象流緩衝區並提供高層輸出界面，如格式化能力｜、`ostream` - 字符類型`char`、`wostream` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_ofstream basic_ofstream]`｜包裝一個文件流緩衝區並提供高層輸出界面，如打開關閉流｜、`ofstream` - 字符類型`char`、`wofstream` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_ostringstream basic_ostringstream]`｜包裝一個字串流緩衝區並提供高層輸出界面，如訪問基礎字串｜、`ostringstream` - 字符類型`char`、`wostringstream` - 字符類型`wchar_t`

Input/output streams buffers (高層功能)

`[http://en.cppreference.com/w/cpp/io/basic_iostream basic_iostream]`｜包裝一個抽象流緩衝區並提供高層輸入輸出界面，如格式化能力｜、`iostream` - 字符類型`char`、`wiostream` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_fstream basic_fstream]`｜包裝一個文件流輸入輸出緩衝區，並提供高層輸入輸出界面，如打開關閉文件｜、`fstream` - 字符類型`char`、`wfstream` - 字符類型`wchar_t`

`[http://en.cppreference.com/w/cpp/io/basic_stringstream basic_stringstream]`｜包裝一個字串流輸入輸出緩衝區，並提供高層輸入輸出界面，如訪問基礎字串｜、`stringstream` - 字符類型`char`、`wstringstream` - 字符類型`wchar_t`

### 頭文件

- `<ios>`包含著`ios_base`與`basic_ios`的類的定義，負責資訊格式化與關聯的流緩衝區。
- `<istream>`包含了`basic_istream`類模板定義，實現了格式化輸入
- `<ostream>`包含了`basic_ostream`類模板定義，實現了格式化輸出
- `<iostream>`包含了`basic_iostream`類模板定義，實現格式化輸入輸出
- `<fstream>`包含了`basic_ifstream`, `basic_ofstream`與`basic_fstream`類模板定義，實現格式化文件流的格式化輸入、輸出
- `<sstream>`包含了`basic_istringstream`, `basic_ostringstream`與`basic_stringstream` 類模板定義，實現格式化字符串流的輸入輸出
- `<iomanip>`包含了格式化manipulator
- `<iosfwd>`包含了所有的流輸入輸出庫的前向聲明（forward declaration）

## 支持類

`[http://en.cppreference.com/w/cpp/io/ios_base ios_base]`與`[http://en.cppreference.com/w/cpp/io/basic_ios basic_ios]`是兩個類處理底層比特流。`ios_base`存儲格式化資訊與流的狀態。`basic_ios`管理關聯的流緩衝區。`basic_ios`通常以特化實例`ios`與`wios`出現。`basic_ios`與`ios_base`很少被程式設計師直接使用。通常，它們的功能通過其它派生的類，如`iostream`。

### Typedefs

名字｜描述

`ios`｜`basic_ios`的`char`類型特化

`wios`｜`basic_ios`的`wchar_t`類型特化

`streamoff`｜支持內部操作

`streampos`｜保存緩衝器指針或文件指針的當前位置

`wstreampos`｜保存寬字符版的緩衝器指針或文件指針的當前位置

`streamsize`｜流的尺寸

### 格式化操縱符（manipulator）

名字｜描述

`[http://en.cppreference.com/w/cpp/io/manip/boolalpha boolalpha]` / `[http://en.cppreference.com/w/cpp/io/manip/boolalpha noboolalpha]`｜指示流中的`bool`類型變量是否以`true`或`false`，還是以`0`或`1`形式出現

`[http://en.cppreference.com/w/cpp/io/manip/skipws skipws]` / `[http://en.cppreference.com/w/cpp/io/manip/skipws noskipws]`｜指示輸入操作時空白符是否被跳過

`[http://en.cppreference.com/w/cpp/io/manip/showbase showbase]` / `[http://en.cppreference.com/w/cpp/io/manip/showbase noshowbase]`｜指示數的基數記數標誌是否顯示

`[http://en.cppreference.com/w/cpp/io/manip/showpoint showpoint]` / `[http://en.cppreference.com/w/cpp/io/manip/showpoint noshowpoint]`｜指示當浮點數小數部分為0時，是否顯示小數部分

`[http://en.cppreference.com/w/cpp/io/manip/showpos showpos]` / `[http://en.cppreference.com/w/cpp/io/manip/showpos noshowpos]`｜指示對於正數是否顯示`+`符號

`[http://en.cppreference.com/w/cpp/io/manip/unitbuf unitbuf]` / `[http://en.cppreference.com/w/cpp/io/manip/unitbuf nounitbuf]`｜指示輸出是否被緩衝

`[http://en.cppreference.com/w/cpp/io/manip/uppercase uppercase]` / `[http://en.cppreference.com/w/cpp/io/manip/uppercase nouppercase]`｜指示在16進位整數或浮點數輸出時是否使用大寫字符

`[http://en.cppreference.com/w/cpp/io/manip/left left]` / `[http://en.cppreference.com/w/cpp/io/manip/left right]` / `[http://en.cppreference.com/w/cpp/io/manip/left internal]`｜指出對齊方式

`[http://en.cppreference.com/w/cpp/io/manip/hex dec]` / `[http://en.cppreference.com/w/cpp/io/manip/hex oct]`/ `[http://en.cppreference.com/w/cpp/io/manip/hex hex]`｜指示顯示整數時的記數法

`[http://en.cppreference.com/w/cpp/io/manip/fixed fixed]` / `[http://en.cppreference.com/w/cpp/io/manip/fixed scientific]`/ `[http://en.cppreference.com/w/cpp/io/manip/fixed hexfloat]`(C++11) / `[http://en.cppreference.com/w/cpp/io/manip/fixed defaultfloat]`(C++11)｜指示浮點數顯示時的記數法

## 輸入/輸出流

`iostream`頭文件定義了輸入輸出流對象：`cin`, `cout`, `cerr`, `clog`分別為標準輸入、輸出、錯誤（無緩衝）、簿記（有緩衝）的流對象。都屬於`std` 命名空間（namespace）。

### ostream對象

`cout`屬於`ostream`類型，重載了左移位算符。cout左移位算符的運算結果為cout自身，這使得連續的左位移操作輸出一串數據成為可能。`cerr`與`clog`對象是`ostream`類型。

### istream對象

`cin`是`istream`類型，重載了右位移算符。

輸入設備是按照行來把數據移入流輸入緩衝區。也就是說，鍵盤輸入數據時，只有按了換行鍵，這一行數據才進入緩衝區，可以讀取。

表達式`cin >> ival`從標準輸入讀入一個值。有兩種情況會使一個istream對象的bool轉型為false：讀到EOF（文件結束標誌）或遇到一個無效的值（輸入流進入fail狀態）。可以用該istream對象的成員函數good來測試，或者直接(bool)cin來測試。

istream對象的bool轉型為false的情況下，此後的所有讀入動作都是無操作（nop）。直到調用istream對象的成員函數clear來清除該對象的內部狀態。

預設情況下，輸入操作符丟棄空白符、空格符、制表符、換行符以及回車。如果希望讀入上述字符，或讀入原始的輸入數據，一種方法是使用istream的get成員函數來讀取一個字符，另一種方法是使用istream的getline成員函數來讀取多個字符。istream的read(char* addr, streamsize size)函數從輸入流中提取size個連續的字節，並將其放在地址從addr開始的記憶體中。istream成員函數gcount返回由最後的get、getline、read調用實際提取的字符數。

輸入流有三個函數來測試流狀態：即bad, fail和eof。ignore用來拋掉制定個數的緩衝區中的字節。

其它的istream成員函數：putback( char c ) 將字符放回iostream；unget往回重置「下一個」istream項；peek返回下一個字符或EOF，但不要提取出來。

## 輸出格式化

### 方法（函數）

`width(int x)`｜下一個輸出的最小字符數目

`fill(char x)`｜填充字符

`precision(int x)`｜設置浮點數的有效數字的位數

### 操縱符（manipulator）

操縱符（manipulator）是使用`<<`或`>>`算子修改流的對象.

`endl`｜"end line": 流中插入換行符並刷新（flush）流的輸出緩衝.

`ends`｜"end string": 向流中插入空字符（null character）並刷新（flush）流的輸出緩衝.

`flush`｜強迫流的輸出緩衝寫出到輸出設備.

`ws`｜導致輸入流吃掉空白（whitespace）

`showpoint`｜指示流要顯示小數點與一些數字0

頭文件中`iomanip`還定義了一些manipulators。

## 批評

某些環境下並不提供共享版本的C++庫。導致程序要靜態編譯入C++標準庫，使得程序的尺寸變大。

## 示例

使用C++寫成的 Hello World 程序如下所示:

```cpp
#include <iostream>
int main()
{
    std::cout << "Hello, world!" << endl; //列印出“Hello, world!”字符，并跳至下一行
    return 0;
}
```

在這段代碼中，文件 iostream 中聲明了程序所要輸入和輸出操作的有關資訊。

下述代碼創建一個文件'file.txt'並寫入文本'Hello World'：

```cpp
#include <fstream>
int main()
{
    std::ofstream file; // 可以与 std::ofstream file("file.txt");
    file.open("file.txt");
    file << "Hello world!\n";
    file.close(); // 不必要，因程序会自动将文件关闭
    return 0;
}
```

使用在C++23新加入的`<print>`標準庫的Hello World 程序如下所示：

```cpp
#include <print>
int main()
{
    std::println("Hello, world!");
    return 0;
}
```

## 外部連結

- C++ reference for input/output library
- Apache C++ Standard Library Iostreams
- Comprehensive tutorial on formatting output in C++.
- Apache C++ Standard Library Iostreams