上一章咱們介紹了有關二進制文件的讀寫。二進制文件比較小巧,卻不是人可讀的格式。而文本文件是一種人可讀的文件。爲了操做這種文件,咱們須要使用QTextStream
類。QTextStream
和QDataStream
的使用相似,只不過它是操做純文本文件的。另外,像 XML、HTML 這種,雖然也是文本文件,能夠由QTextStream
生成,但 Qt 提供了更方便的 XML 操做類,這裏就不包括這部份內容了。git
QTextStream
會自動將 Unicode 編碼同操做系統的編碼進行轉換,這一操做對開發人員是透明的。它也會將換行符進行轉換,一樣不須要本身處理。QTextStream
使用 16 位的QChar
做爲基礎的數據存儲單位,一樣,它也支持 C++ 標準類型,如 int 等。實際上,這是將這種標準類型與字符串進行了相互轉換。緩存
QTextStream
同QDataStream
的使用基本一致,例以下面的代碼將把「The answer is 42」寫入到 file.txt 文件中:函數
QFile data("file.txt"); if (data.open(QFile::WriteOnly | QIODevice::Truncate)) { QTextStream out(&data); out << "The answer is " << 42; }
這裏,咱們在open()
函數中增長了QIODevice::Truncate
打開方式。咱們能夠從下表中看到這些打開方式的區別:編碼
枚舉值 | 描述 |
QIODevice::NotOpen |
未打開 |
QIODevice::ReadOnly |
以只讀方式打開 |
QIODevice::WriteOnly |
以只寫方式打開 |
QIODevice::ReadWrite |
以讀寫方式打開 |
QIODevice::Append |
以追加的方式打開,新增長的內容將被追加到文件末尾 |
QIODevice::Truncate |
以重寫的方式打開,在寫入新的數據時會將原有數據所有清除,遊標設置在文件開頭。 |
QIODevice::Text |
在讀取時,將行結束符轉換成 \n;在寫入時,將行結束符轉換成本地格式,例如 Win32 平臺上是 \r\n |
QIODevice::Unbuffered |
忽略緩存 |
咱們在這裏使用了QFile::WriteOnly | QIODevice::Truncate
,也就是以只寫而且覆蓋已有內容的形式操做文件。注意,QIODevice::Truncate
會直接將文件內容清空。操作系統
雖然QTextStream
的寫入內容與QDataStream
一致,可是讀取時卻會有些困難:code
QFile data("file.txt"); if (data.open(QFile::ReadOnly)) { QTextStream in(&data); QString str; int ans = 0; in >> str >> ans; }
在使用QDataStream
的時候,這樣的代碼很方便,可是使用了QTextStream
時卻有所不一樣:讀出的時候,str 裏面將是 The answer is 42,ans 是 0。這是由於以文本形式寫入數據,是沒有數據之間的分隔的。還記得咱們前面曾經說過,使用QDataStream
寫入的時候,實際上會在要寫入的內容前面,額外添加一個這段內容的長度值。而文本文件則沒有相似的操做。所以,使用文本文件時,不多會將其分割開來讀取,而是使用諸如QTextStream::readLine()
讀取一行,使用QTextStream::readAll()
讀取全部文本這種函數,以後再對得到的QString
對象進行處理。對象
默認狀況下,QTextStream
的編碼格式是 Unicode,若是咱們須要使用另外的編碼,可使用ip
stream.setCodec("UTF-8");
這樣的函數進行設置。ci
另外,爲方便起見,QTextStream
同std::cout
同樣提供了不少描述符,被稱爲 stream manipulators。由於文本文件是供人去讀的,天然須要良好的格式(相比而言,二進制文件就沒有這些問題,只要數據準確就能夠了)。這些描述符是一些函數的簡寫,咱們能夠從文檔中找到:開發
描述符 | 等價於 |
bin |
setIntegerBase(2) |
oct |
setIntegerBase(8) |
dec |
setIntegerBase(10) |
hex |
setIntegerBase(16) |
showbase |
setNumberFlags(numberFlags() | ShowBase) |
forcesign |
setNumberFlags(numberFlags() | ForceSign) |
forcepoint |
setNumberFlags(numberFlags() | ForcePoint) |
noshowbase |
setNumberFlags(numberFlags() & ~ShowBase) |
noforcesign |
setNumberFlags(numberFlags() & ~ForceSign) |
noforcepoint |
setNumberFlags(numberFlags() & ~ForcePoint) |
uppercasebase |
setNumberFlags(numberFlags() | UppercaseBase) |
uppercasedigits |
setNumberFlags(numberFlags() | UppercaseDigits) |
lowercasebase |
setNumberFlags(numberFlags() & ~UppercaseBase) |
lowercasedigits |
setNumberFlags(numberFlags() & ~UppercaseDigits) |
fixed |
setRealNumberNotation(FixedNotation) |
scientific |
setRealNumberNotation(ScientificNotation) |
left |
setFieldAlignment(AlignLeft) |
right |
setFieldAlignment(AlignRight) |
center |
setFieldAlignment(AlignCenter) |
endl |
operator<<('\n') 和flush() |
flush |
flush() |
reset |
reset() |
ws |
skipWhiteSpace() |
bom |
setGenerateByteOrderMark(true) |
這些描述符只是一些函數的簡寫。例如,咱們想要輸出 12345678 的二進制形式,那麼能夠直接使用
out << bin << 12345678;
就能夠了。這等價於
out.setIntegerBase(2); out << 12345678;
更復雜的,若是咱們想要舒服 1234567890 的帶有前綴、所有字母大寫的十六進制格式(0xBC614E),那麼只要使用
out << showbase << uppercasedigits << hex << 12345678;
便可。
不只是QIODevice
,QTextStream
也能夠直接把內容輸出到QString
。例如
QString str; QTextStream(&str) << oct << 31 << " " << dec << 25 << endl;
這提供了一種簡單的處理字符串內容的方法。