C++ でドキュメントをロードする方法

C++ でドキュメントをロードする方法

Aspose.PDF FOSS for C++ は、Document クラスを介して既存の PDF を開きます — 単純なファイルパスから、またはソースが暗号化されている場合はパスワードで — そしてファイルの /Info メタデータを DocumentInfo を通じて公開します。このガイドでは、ドキュメントのロード、パスワード保護されたファイルの検出とオープン、title/author/producer メタデータの読み取りと更新、そして結果の保存について説明します。ライブラリは CMake を通じてプロジェクトに追加されます;パッケージマネージャによるインストール手順はありません。

ステップバイステップガイド

ステップ 1: パッケージをインストールする

ライブラリを CMake のサブディレクトリとして追加し、aspose_pdf_foss ターゲットにリンクします:

add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)

ツールチェーンとヘッダーが解決することを、最小限のプログラムをコンパイルして確認します:

#include <aspose/pdf/document.hpp>
#include <iostream>

int main() {
    Aspose::Pdf::Document doc;
    std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}

pages: 0 を出力するビルドが成功すれば、ライブラリが正しくリンクされていることが確認できます。


ステップ 2: 必要なクラスをインポートする

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>

using namespace Aspose::Pdf;

Document と DocumentInfo はどちらも Aspose::Pdf 名前空間の直下で宣言されています。


ステップ 3: ファイルパスから PDF ドキュメントを開く

Document(filename) コンストラクタはファイルを読み取り、クロスリファレンステーブルとページツリーを解析し、インメモリモデルを構築します。ファイルが存在しない、または読み取れない場合は std::system_error をスローし、ファイルが有効な PDF でない場合は std::runtime_error をスローします:

#include <iostream>
#include <stdexcept>

try {
    Document doc("input.pdf");
    std::cout << "Pages: " << doc.Pages().Count() << "\n";
} catch (const std::runtime_error& e) {
    std::cerr << "Not a valid PDF: " << e.what() << "\n";
} catch (const std::system_error& e) {
    std::cerr << "Could not read file: " << e.what() << "\n";
}

ステップ 4: パスワード保護されたドキュメントを開く

ステップ 3 の単一引数コンストラクタはパスワードを認証したり、トレーラの /Encrypt エントリを検査したりしないため、その方法で開いたドキュメントに対する IsEncrypted() は常に false を報告します――実際にソースファイルが暗号化されている場合でもです。暗号化された PDF を検出して開くには、二引数コンストラクタを使用します。このコンストラクタは /Encrypt を読み取り、指定したパスワードを認証します:

try {
    Document doc("input.pdf", "user-password");
    if (doc.IsEncrypted()) {
        std::cout << "Opened an encrypted document.\n";
    }
} catch (const std::runtime_error& e) {
    // Thrown when /Encrypt is present and the password matches
    // neither the user nor the owner entry in the trailer.
    std::cerr << "Wrong password or unreadable /Encrypt dictionary: "
              << e.what() << "\n";
}

ソース PDF が暗号化されていない場合、パスワード引数は単に無視され、ドキュメントは通常どおりに開かれます――したがって、ファイルが保護されているか確信が持てなくても二引数コンストラクタを使用しても安全です。


ステップ 5: DocumentInfo を使用してドキュメントメタデータを読み取る

Document.Info() は、ドキュメントの /Info 辞書にバインドされた DocumentInfo& を返します。各事前定義フィールドには独自の読み取りアクセサがあり、キーがソースファイルに存在しない場合は空文字列を返します。:

Document doc("input.pdf");
DocumentInfo& info = doc.Info();

std::cout << "Title: "    << info.Title()    << "\n";
std::cout << "Author: "   << info.Author()   << "\n";
std::cout << "Subject: "  << info.Subject()  << "\n";
std::cout << "Producer: " << info.Producer() << "\n";
std::cout << "Creator: "  << info.Creator()  << "\n";
std::cout << "Keywords: " << info.Keywords() << "\n";

DocumentInfo::IsPredefinedKey は、指定された /Info キー名がこれらの組み込みフィールドのいずれかであるかどうかを報告し、Add で追加されたカスタムキーとは区別します。:

bool builtin = DocumentInfo::IsPredefinedKey("Title");   // true
bool custom  = DocumentInfo::IsPredefinedKey("MyKey");   // false

ステップ 6: メタデータを更新してドキュメントを保存する

対応するセッターのオーバーロード、または Document 上の SetTitle 便利メソッドを使ってメタデータを設定し、変更は Save で永続化します。:

Document doc("input.pdf");
doc.Info().Author("Report Generator");
doc.SetTitle("Quarterly Report");   // equivalent to doc.Info().Title(title)

doc.Save("output.pdf");

メタデータの編集はメモリ上でステージングされ、次の Save 呼び出し時にのみ書き出されます。新しいパスへ書き込むには Save(outputFileName) を呼び出し、元のドキュメントが開かれたファイルを上書きするには引数なしの Save() を使用します。:

Document doc("input.pdf");
doc.SetTitle("Updated In Place");
doc.Save();   // writes back to "input.pdf"

一般的な問題と解決策

IsEncrypted() returns false パスワードで保護されていることが分かっている PDF の場合

単一引数の Document(path) コンストラクタはファイルの /Encrypt 辞書に対して認証を行わないため、IsEncrypted() はこの方法で開かれたドキュメントで常に false を報告します。ソースが実際に暗号化されているかどうかに関係なくです。代わりに二引数の Document(path, password) コンストラクタでファイルを開いてください—暗号化状態を設定する唯一のオーバーロードです。

2 引数コンストラクタは例外をスローします std::runtime_error

これは、ソース PDF のトレーラに /Encrypt エントリがあり、提供されたパスワードがそこに記録されたユーザーパスワードでもオーナーパスワードでも一致しなかったことを意味します。std::runtime_error を捕捉して正しいパスワードを促すか、再試行する前に別途パスワードを確認してください。

Save() 「no source filename to save to」という例外をスローします

引数なしの Save() は、ドキュメントが構築されたパスへ書き戻します。引数なしコンストラクタで作成された Document(ソースファイルを持たない新しいインメモリドキュメント)には書き戻すパスが存在しないため、Save() がスローされます。代わりに Save(outputFileName) を呼び出してください。

Decrypt() 保護されていないファイルが生成されないようです

Decrypt() はインメモリの IsEncrypted() フラグをクリアし、以降の読み取りでドキュメントをプレーンテキストとして扱いますが、現在のリリースではトレーラの /Encrypt 辞書を書き換えたり、暗号化された文字列やストリームを再エンコードしたりしません。Decrypt() の後に Save() を呼び出しても、元のバイト(元の暗号化を含む)を書き戻すだけです—このメソッドはまだディスク上にプレーンテキストのコピーを生成しません。

Title/Author/etc. が空文字列として出力されます

DocumentInfo アクセサは、対応する /Info キーがソース PDF に存在しない場合、エラーではなく空文字列を返します。空の結果は、そのフィールドがそのドキュメントで設定されていなかったことを意味し、読み取りが失敗したことを意味するわけではありません。

よくある質問

暗号化された PDF で Document(path) は動作しますか?

通常、例外を投げることなくページツリーを解析しますが、パスワードを認証することはなく、常に IsEncrypted() を false のままにします。ソースが暗号化されている可能性がある場合は、常に 2 引数コンストラクタを使用してください。

暗号化されていないことが判明したファイルに対して、Document(path, password) にパスワードを渡すのは安全ですか?

はい。トレーラに /Encrypt エントリがない場合、パスワード引数は無視され、ドキュメントは単一引数コンストラクタを使用した場合と同様に開かれます。

カスタム /Info キーと組み込みキーをどのように区別できますか?

静的な DocumentInfo::IsPredefinedKey(key) を呼び出してください。Title、Author、Subject、Keywords、Creator、Producer、および Trapped に対しては true を返し、それ以外のものに対しては false を返します。

ロードしたばかりのファイルを新しいパスに書き込むのではなく、上書きできますか?

はい — ファイルパスから構築された Document に対して引数なしの Save() を呼び出します;それは同じソースパスに書き戻します。ソースパスがない、引数なしコンストラクタで作成されたドキュメントに対しては例外がスローされます。

Decrypt() の後に保存すると、PDF のパスワード保護は解除されますか?

いいえ、現在のリリースでは対応していません — 上記の Common Issues を参照してください。Decrypt() はコンテンツリーダーが使用するメモリ上の状態にのみ影響し、Save() が書き出すファイルは元の /Encrypt 辞書を引き続き保持します。

参照

 日本語