QTextStreamだけじゃない!Qtでファイル読み込みを極める代替メソッド

2025-05-27

QTextStream::read()メソッドは、特定のバイト数を読み取るために使用されるメソッドです。ただし、通常、QTextStreamでテキストを読み取る際には、read()メソッドが直接使われることはあまり多くありません。 その代わりに、以下のようなより高レベルで便利なメソッドがよく使われます。

QTextStreamでよく使われる読み取りメソッド

  • C++のストリーム演算子(>>: QTextStreamはC++標準ライブラリのストリームと同様に、>>演算子を使って単語や数値などを読み取ることができます。これは、スペース区切りや改行区切りのデータを読み取る場合に便利です。

    QTextStream in(someString); // 例としてQStringから読み込む場合
    QString word;
    int number;
    in >> word >> number; // 最初の単語と次の数値を読み込む
    qDebug() << "単語: " << word << ", 数値: " << number;
    
  • QString QTextStream::readLine(): これは、ストリームから改行文字(\n)が現れるまで、またはストリームの末尾に達するまでテキストを読み込み、その行をQStringとして返します。 改行文字は返される文字列には含まれません。行ごとに処理したい場合に適しています。

    QFile file("myfile.txt");
    if (file.open(QFile::ReadOnly | QFile::Text)) {
        QTextStream in(&file);
        while (!in.atEnd()) { // ストリームの終端に達するまで
            QString line = in.readLine();
            qDebug() << "読み込んだ行: " << line;
        }
        file.close();
    }
    
  • QString QTextStream::readAll(): これは最も一般的に使われるメソッドで、ストリーム内のすべての残りのテキストを一度に読み込み、QStringとして返します。 ファイル全体を読み込む場合などに非常に便利です。

    例:

    QFile file("myfile.txt");
    if (file.open(QFile::ReadOnly | QFile::Text)) {
        QTextStream in(&file);
        QString allText = in.readAll();
        qDebug() << allText;
        file.close();
    }
    

QTextStream::read() の具体的な用途(低レベル)

QTextStream::read(qint64 maxLength) メソッドは、指定された最大バイト数(maxLength)までテキストを読み取り、QStringとして返します。通常、これを使うのは、特定のバイト数だけを厳密に読み込みたい、あるいは非常に大きなファイルを少しずつ読み込みたいなど、より低レベルな制御が必要な場合です。

QFile file("largefile.txt");
if (file.open(QFile::ReadOnly | QFile::Text)) {
    QTextStream in(&file);
    // 最初の100バイトを読み込む(実際には文字数として解釈されるため注意が必要)
    QString partOfText = in.read(100); 
    qDebug() << partOfText;
    file.close();
}

重要な注意点
read(qint64 maxLength)は「バイト数」を指定しますが、QTextStreamは内部でテキストエンコーディング(UTF-8、Shift-JISなど)を考慮して文字を扱います。そのため、例えばUTF-8でマルチバイト文字が含まれる場合、指定したバイト数と実際の文字数が一致しないことがあります。通常、テキストファイルを文字単位で処理したい場合は、readLine()readAll()、または>>演算子を使う方が直感的で安全です。

QTextStream::setCodec()メソッドを使ってエンコーディングを設定できます。

QFile file("japanese_text.txt");
if (file.open(QFile::ReadOnly | QFile::Text)) {
    QTextStream in(&file);
    // UTF-8で保存されたファイルを読み込む場合
    in.setCodec("UTF-8"); 
    // Shift-JISで保存されたファイルを読み込む場合
    // in.setCodec("Shift-JIS"); 
    QString text = in.readAll();
    qDebug() << text;
    file.close();
}


ファイルが見つからない、または開けない (File Not Found / Cannot Open File)

よくあるエラー

  • Windowsの場合、バックスラッシュ\をエスケープしていない("C:\\path\\to\\file.txt"ではなく"C:/path/to/file.txt"を使う方が安全で推奨される)。
  • ファイルへのアクセス権限がない。
  • 実行ファイルからの相対パスが期待と異なる。
  • ファイルパスのスペルミス、大文字/小文字の区別(特にLinux/macOS)。
  • ファイルが存在しないパスを指定している。

トラブルシューティング

  1. ファイルの存在確認
    QFile::exists() を使用して、ファイルが実際に指定されたパスに存在するか確認します。
    QFile file("path/to/your/file.txt");
    if (!file.exists()) {
        qDebug() << "エラー: ファイルが見つかりません。";
        return;
    }
    
  2. ファイルのオープン確認
    QFile::open() の戻り値を必ずチェックし、失敗した場合は QFile::errorString() でエラーメッセージを確認します。
    QFile file("path/to/your/file.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "エラー: ファイルを開けません。" << file.errorString();
        return;
    }
    QTextStream in(&file);
    // ... 読み取り処理 ...
    file.close();
    
  3. パスの絶対パス化
    相対パスではなく、QCoreApplication::applicationDirPath()QDir::currentPath() などを使って絶対パスを指定してみることで、パスの問題を切り分けられます。
    QString filePath = QCoreApplication::applicationDirPath() + "/data/myfile.txt";
    QFile file(filePath);
    // ...
    
  4. アクセス権限
    ファイルが読み取り可能か、ユーザーまたはプロセスに適切な権限があるかを確認します。

文字化け (Encoding Issues)

よくあるエラー

  • BOM(Byte Order Mark)の有無が考慮されていない。
  • ファイルのエンコーディングと QTextStream のエンコーディング設定が一致していない。

トラブルシューティング

  1. autoDetectUnicode()
    QTextStream はデフォルトでUTF-8, UTF-16, UTF-32のBOMを自動検出します。BOMがないUTF-8ファイルの場合、正しく検出されないことがあります。その場合は明示的に setCodec("UTF-8") を呼び出すのが最も確実です。

空の文字列が返される / データが読み取れない (Empty String / No Data Read)

よくあるエラー

  • QFileQTextStreamを混在して使用し、内部ポインタがずれている。
  • QFile::open() が読み取りモードで正しく開かれていない。
  • ストリームの位置が既にファイルの終端に達している。
  • ファイルが空である。

トラブルシューティング

  1. ファイルのサイズ確認
    ファイルを読み取る前に、QFile::size() を確認して、ファイルが本当に空ではないかチェックします。
  2. QFile::open() のモード確認
    QIODevice::ReadOnly | QIODevice::Text を使用しているか確認します。QIODevice::Textフラグは、改行コードの自動変換(WindowsのCRLFをLFに変換するなど)のために重要です。
  3. ストリームの終端チェック
    ループで読み取る際に !in.atEnd() を使用しますが、初期状態で atEnd()true を返すことがあります。これは、QIODeviceの種類(例: ソケットのようなシーケンシャルデバイス)によっては、データがまだ来ていないと判断されるためです。ファイルからの読み取りでは通常問題ありませんが、念のため do-while ループを使うことが推奨される場合があります。
    QTextStream in(&file);
    QString line;
    do {
        line = in.readLine();
        if (!line.isNull()) { // readLine() はEOFで空文字列を返す
            qDebug() << line;
        }
    } while (!line.isNull()); // line.isNull() はストリームの終端に達したことを示す
    
    注意点: QTextStream::read(maxLength) を使用する場合、maxLength がファイルの残りのサイズより大きいと、残りのすべてのデータが読み取られます。
  4. QFileとQTextStreamの排他的使用
    QTextStreamQFile に設定した後は、QFile の低レベルな読み取りメソッド(例: QFile::read()QFile::readLine()) を直接呼び出さないでください。QTextStream は独自のバッファを持つため、これらを混在させるとストリームの内部位置がずれて、期待通りの動作をしなくなることがあります。

大容量ファイルの読み込みによるUIフリーズ (UI Freeze with Large Files)

よくあるエラー

  • ループ内で readLine() を使ってUIコンポーネントを頻繁に更新している。
  • 大容量のファイルを readAll() で一度に読み込もうとすると、その処理に時間がかかり、アプリケーションのUIがフリーズする。

トラブルシューティング

  1. QThread を使用した非同期処理
    ファイル読み込み処理を別のスレッド(QThread)で実行し、読み込み完了後にUIスレッドにシグナルを送って結果を反映させます。これにより、UIの応答性を保つことができます。
  2. QtConcurrent の使用
    より簡単に非同期処理を実現するために QtConcurrent::run() を使用することもできます。
    #include <QtConcurrent>
    #include <QFutureWatcher>
    
    // ...
    
    QFile *file = new QFile("large_file.txt");
    if (file->open(QFile::ReadOnly | QFile::Text)) {
        QTextStream *in = new QTextStream(file);
        in->setCodec("UTF-8"); // 必要に応じてエンコーディングを設定
    
        QFutureWatcher<QString> *watcher = new QFutureWatcher<QString>(this);
        connect(watcher, &QFutureWatcher<QString>::finished, this, [=]() {
            QString result = watcher->result();
            qDebug() << "ファイル読み込み完了。サイズ:" << result.length();
            // UIに結果を反映する処理 (例: textEdit->setText(result); )
            file->close();
            file->deleteLater();
            watcher->deleteLater();
        });
    
        QFuture<QString> future = QtConcurrent::run([=]() {
            return in->readAll(); // readAll() はメインスレッドから切り離されて実行される
        });
        watcher->setFuture(future);
    } else {
        qDebug() << "ファイルを開けません。";
        delete file;
    }
    

よくあるエラー

  • シーケンシャルデバイス(例: ネットワークソケット、標準入力 stdin)に対して atEnd() が常に true を返すと勘違いする、またはその挙動を知らない。
  • stdin のようなデバイスでは、atEnd() ではなく、readLine() が空の文字列を返すか、または canReadLine()true を返すかどうかに基づいて判断する必要があります。
  • ファイルの場合、!in.atEnd() は有効ですが、readLine()isNull() を返すかどうかでループを制御する方が確実な場合があります。
  • QIODevice::atEnd() のドキュメントを確認します。特にシーケンシャルデバイスの場合、データの終端に達したことを示すのではなく、「現在、読み取るデータがない」ことを示している場合があります。


QTextStream を使うには、QFileQString などの QIODevice を継承したオブジェクトを渡す必要があります。

例1: ファイル全体を一度に読み込む (readAll())

最も一般的な使い方の一つです。小さなテキストファイルや、ファイル全体の内容を一度にメモリに読み込みたい場合に適しています。

main.cpp

#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug> // デバッグ出力用

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 読み込むファイルの名前
    QString fileName = "my_text_file.txt";

    // QFile オブジェクトを作成
    QFile file(fileName);

    // ファイルを読み取りモードで開く
    // QIODevice::ReadOnly: 読み取り専用
    // QIODevice::Text: テキストモード(改行コードの自動変換など)
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "ファイルを開けませんでした:" << file.errorString();
        return 1; // エラー終了
    }

    // QTextStream オブジェクトを作成し、ファイルに関連付ける
    QTextStream in(&file);

    // ファイル全体を読み込み、QString に格納
    QString content = in.readAll();

    // 読み込んだ内容を表示
    qDebug() << "ファイルの内容:\n" << content;

    // ファイルを閉じる(QFile のデストラクタが自動的に閉じるが、明示的に閉じることも可能)
    file.close();

    return 0;
}

my_text_file.txt (作成してください)

これは
テストファイルです。
日本語のテキストも含まれます。
一行目
二行目

実行結果

ファイルの内容:
"これは
テストファイルです。
日本語のテキストも含まれます。
一行目
二行目"

例2: ファイルを1行ずつ読み込む (readLine())

ファイルを行ごとに処理したい場合に便利です。例えば、CSVファイルやログファイルを解析する際などに使用します。

main.cpp

#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString fileName = "my_text_file.txt";
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "ファイルを開けませんでした:" << file.errorString();
        return 1;
    }

    QTextStream in(&file);

    qDebug() << "行ごとの内容:";
    int lineNumber = 1;
    // ファイルの終端に達するまでループ
    while (!in.atEnd()) {
        QString line = in.readLine(); // 1行読み込む
        qDebug() << QString("行 %1: %2").arg(lineNumber).arg(line);
        lineNumber++;
    }

    file.close();

    return 0;
}

実行結果

行ごとの内容:
行 1: "これは"
行 2: "テストファイルです。"
行 3: "日本語のテキストも含まれます。"
行 4: "一行目"
行 5: "二行目"

例3: 特定のバイト数(文字数)だけ読み込む (read(qint64 maxLength))

あまり一般的ではありませんが、特定の文字数だけを読み込みたい場合に使用します。QTextStream はテキストエンコーディングを考慮して文字を処理するため、指定した maxLength はバイト数ではなく「文字数」として解釈されます。

main.cpp

#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString fileName = "my_text_file.txt";
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "ファイルを開けませんでした:" << file.errorString();
        return 1;
    }

    QTextStream in(&file);

    // 最初の10文字を読み込む
    QString first10Chars = in.read(10);
    qDebug() << "最初の10文字:\n" << first10Chars;

    // 残りのすべてを読み込む
    QString remainingChars = in.readAll();
    qDebug() << "残りの文字:\n" << remainingChars;

    file.close();

    return 0;
}

実行結果

最初の10文字:
"これは
テスト"
残りの文字:
"ファイルです。
日本語のテキストも含まれます。
一行目
二行目"

例4: 文字化け対策(エンコーディング設定)

main.cpp

#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QTextCodec> // エンコーディング設定用

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString fileName = "japanese_text.txt"; // 日本語を含むファイル
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "ファイルを開けませんでした:" << file.errorString();
        return 1;
    }

    QTextStream in(&file);

    // ファイルのエンコーディングがUTF-8であると仮定して設定
    // Shift-JIS の場合は in.setCodec(QTextCodec::codecForName("Shift-JIS"));
    in.setCodec("UTF-8"); 

    QString content = in.readAll();
    qDebug() << "日本語ファイルの内容:\n" << content;

    file.close();

    return 0;
}
こんにちは、世界!
これは日本語のテストです。
文字化けせずに読めますか?

実行結果

日本語ファイルの内容:
"こんにちは、世界!
これは日本語のテストです。
文字化けせずに読めますか?"

コンソールアプリケーションでユーザーからの入力を読み込む場合にも QTextStream は使用できます。

main.cpp

#include <QCoreApplication>
#include <QTextStream>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 標準入力から読み取るための QTextStream を作成
    QTextStream in(stdin);
    QTextStream out(stdout); // 標準出力へ書き出すための QTextStream

    out << "何か入力してください (終了するには Ctrl+D または Ctrl+Z): ";
    out.flush(); // プロンプトをすぐに表示

    QString line;
    // 標準入力の終端(EOF)に達するまで行を読み込む
    while (!in.atEnd()) {
        line = in.readLine();
        if (!line.isEmpty()) { // 空行でなければ表示
            out << "入力された行: " << line << Qt::endl; // Qt::endl は改行とフラッシュ
            out << "続けて入力してください: ";
            out.flush();
        }
    }

    out << "入力が終了しました。" << Qt::endl;

    return 0;
}
何か入力してください (終了するには Ctrl+D または Ctrl+Z): Hello Qt
入力された行: Hello Qt
続けて入力してください: こんにちは
入力された行: こんにちは
続けて入力してください: (ここで Ctrl+D または Ctrl+Z)
入力が終了しました。


ここでは、QTextStream の代替となるプログラミング方法をいくつかご紹介します。

低レベルなバイト単位の読み込み (QFile::read(), QFile::readAll(), QFile::readLine())

QTextStream は内部的にエンコーディングを考慮してテキストを処理しますが、QFile はより低レベルなバイトデータとしてファイルを扱います。バイナリファイルや、エンコーディング変換を自分で制御したい場合に適しています。

  • QFile::readLine(qint64 maxLength = 0): ファイルから1行を QByteArray として読み込みます。QIODevice::Text フラグが設定されている場合、改行コードはシステム標準に変換されます。
  • QFile::read(qint64 maxSize): 指定された最大バイト数までを QByteArray として読み込みます。
  • QFile::readAll(): ファイル全体を QByteArray として読み込みます。

使い分けのポイント

  • メモリ効率を重視する大容量テキストファイル: QFile::readLine() で行ごとに QByteArray を読み込み、必要に応じて QString::fromUtf8() などで QString に変換して処理します。
  • テキストファイルでエンコーディングを厳密に制御したい: QFile::readAll() でバイトデータを読み込み、自分で QTextCodec を使って QString に変換します。
  • バイナリファイル: QTextStream は使わず、QFile::read()QFile::readAll() を使います。

例: ファイルを QByteArray として読み込み、UTF-8で QString に変換

#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <QTextCodec>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString fileName = "my_text_file.txt"; // 例: UTF-8で保存されたファイル
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly)) { // QIODevice::Text は付けない(バイトとして扱うため)
        qWarning() << "ファイルを開けませんでした:" << file.errorString();
        return 1;
    }

    QByteArray fileData = file.readAll(); // ファイル全体をバイト配列として読み込む
    file.close();

    // UTF-8Codec を使用してバイト配列を QString に変換
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    if (!codec) {
        qWarning() << "UTF-8 コーデックが見つかりません。";
        return 1;
    }
    QString content = codec->toUnicode(fileData);

    qDebug() << "QByteArray から読み込んだ内容:\n" << content;

    return 0;
}

データ構造化されたバイナリファイルの読み込み (QDataStream)

QTextStream がテキスト(人間が読める形式)を扱うのに対し、QDataStream は**バイナリデータ(機械が効率的に読み書きする形式)**を扱います。Qt の組み込み型(QString, QList, QMap など)を直接シリアライズ・デシリアライズするのに非常に強力です。

使い分けのポイント

  • バージョン管理: QDataStream::setVersion() を使うことで、異なるバージョンのアプリケーション間での互換性を維持できます。
  • パフォーマンス: テキストのパースやエンコーディング変換のオーバーヘッドがないため、高速です。
  • アプリケーション固有のデータ形式: 設定ファイル、ゲームのセーブデータなど、アプリケーション間で共有するバイナリ形式のデータを扱うのに適しています。

例: 数値と文字列をバイナリ形式でファイルに書き込み、読み込む

#include <QCoreApplication>
#include <QFile>
#include <QDataStream>
#include <QDebug>

// データをファイルに書き込む関数
void writeData(const QString &fileName) {
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "ファイルに書き込めませんでした:" << file.errorString();
        return;
    }

    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_5_15); // Qtのバージョンを指定して互換性を確保

    // データを書き込む
    out << QString("Hello, QDataStream!"); // 文字列
    out << 123;                           // 整数
    out << 45.67;                         // 浮動小数点数
    out << QList<int>() << 1 << 2 << 3;   // リスト

    file.close();
    qDebug() << "データをファイルに書き込みました。";
}

// ファイルからデータを読み込む関数
void readData(const QString &fileName) {
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "ファイルを読み込めませんでした:" << file.errorString();
        return;
    }

    QDataStream in(&file);
    in.setVersion(QDataStream::Qt_5_15); // 書き込み時と同じバージョンを指定

    // データを読み込む
    QString str;
    int num1;
    double num2;
    QList<int> intList;

    in >> str >> num1 >> num2 >> intList;

    file.close();

    qDebug() << "ファイルから読み込んだ内容:";
    qDebug() << "文字列:" << str;
    qDebug() << "整数:" << num1;
    qDebug() << "浮動小数点数:" << num2;
    qDebug() << "リスト:" << intList;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString dataFileName = "my_data_file.dat";
    writeData(dataFileName);
    readData(dataFileName);

    return 0;
}

テキストファイルでも、JSONやXMLのような構造化された形式でデータが保存されている場合、それぞれの形式に特化したQtのクラスを使用する方が、QTextStream で手動でパースするよりもはるかに効率的で安全です。

a. JSONデータの読み込み (QJsonDocument, QJsonObject, QJsonArray)

使い分けのポイント

  • キーと値のペア、配列構造を直感的に扱えます。
  • Web APIからのデータ受信や、モダンな設定ファイルでよく使われます。

例: JSONファイルを読み込む

my_data.json (作成してください)

{
    "name": "Qt Application",
    "version": "1.0",
    "features": ["file_io", "network", "gui"],
    "settings": {
        "theme": "dark",
        "loglevel": "info"
    }
}

main.cpp

#include <QCoreApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString fileName = "my_data.json";
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "JSONファイルを開けませんでした:" << file.errorString();
        return 1;
    }

    QByteArray jsonData = file.readAll();
    file.close();

    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);

    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "JSONパースエラー:" << parseError.errorString();
        return 1;
    }

    if (doc.isObject()) {
        QJsonObject obj = doc.object();

        qDebug() << "Name:" << obj["name"].toString();
        qDebug() << "Version:" << obj["version"].toString();

        if (obj.contains("features") && obj["features"].isArray()) {
            QJsonArray featuresArray = obj["features"].toArray();
            qDebug() << "Features:";
            for (const QJsonValue &value : featuresArray) {
                qDebug() << "- " << value.toString();
            }
        }

        if (obj.contains("settings") && obj["settings"].isObject()) {
            QJsonObject settingsObj = obj["settings"].toObject();
            qDebug() << "Settings:";
            qDebug() << "  Theme:" << settingsObj["theme"].toString();
            qDebug() << "  LogLevel:" << settingsObj["loglevel"].toString();
        }
    }

    return 0;
}

b. XMLデータの読み込み (QXmlStreamReader, QDomDocument)

Qt にはXMLをパースするためのクラスが複数あります。

  • QDomDocument: DOM(Document Object Model)ベースのパーサーで、XML文書全体をツリー構造としてメモリに読み込みます。小〜中規模のXMLファイルや、ランダムアクセスで要素にアクセスしたい場合に便利です。
  • QXmlStreamReader: ストリームベースのパーサーで、XML文書を線形に読み進めます。大容量のXMLファイルや、部分的に処理したい場合に効率的です。

使い分けのポイント

  • 小〜中規模XMLファイル/ツリー構造でのアクセス: QDomDocument
  • 大容量XMLファイル/ストリーム処理: QXmlStreamReader

例: QXmlStreamReader でXMLファイルを読み込む

my_config.xml (作成してください)

<config>
    <application name="MyApp" version="1.0">
        <module id="1">
            <name>Core</name>
            <enabled>true</enabled>
        </module>
        <module id="2">
            <name>Plugins</name>
            <enabled>false</enabled>
        </module>
    </application>
</config>
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString fileName = "my_config.xml";
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "XMLファイルを開けませんでした:" << file.errorString();
        return 1;
    }

    QXmlStreamReader xml(&file);

    while (!xml.atEnd() && !xml.hasError()) {
        QXmlStreamReader::TokenType token = xml.readNext(); // 次のトークンを読み込む

        // ドキュメントの開始/終了はスキップ
        if (token == QXmlStreamReader::StartDocument || token == QXmlStreamReader::EndDocument) {
            continue;
        }

        if (token == QXmlStreamReader::StartElement) { // 開始タグの場合
            if (xml.name() == "application") {
                qDebug() << "アプリケーション名:" << xml.attributes().value("name").toString();
                qDebug() << "バージョン:" << xml.attributes().value("version").toString();
            } else if (xml.name() == "module") {
                qDebug() << "--- モジュール ID:" << xml.attributes().value("id").toString();
            } else if (xml.name() == "name") {
                xml.readNext(); // 要素内のテキストを読み込む
                if (xml.tokenType() == QXmlStreamReader::Characters) {
                    qDebug() << "  名前:" << xml.text().toString();
                }
            } else if (xml.name() == "enabled") {
                xml.readNext();
                if (xml.tokenType() == QXmlStreamReader::Characters) {
                    qDebug() << "  有効:" << (xml.text().toString() == "true" ? "はい" : "いいえ");
                }
            }
        }
    }

    if (xml.hasError()) {
        qWarning() << "XMLパースエラー:" << xml.errorString();
    }

    file.close();

    return 0;
}
  • QXmlStreamReader / QDomDocument: XML形式の構造化されたテキストデータを扱う場合に用いる。
  • QJsonDocument / QJsonArray / QJsonObject: JSON形式の構造化されたテキストデータを扱う場合に用いる。
  • QDataStream: アプリケーション固有のバイナリ形式のデータを効率的にシリアライズ・デシリアライズしたい場合に用いる。
  • QFile 直接読み込み: バイナリファイルや、テキストファイルのバイトデータを自分で制御して読み書きしたい場合に用いる。
  • QTextStream: 人間が読めるテキストファイル(プレーンテキスト、ログファイル、CSVなど)を文字列として読み書きする場合の標準的な選択肢。エンコーディング変換を自動的に行ってくれる。