PythonでPDFをバイト（bytesとbytearray）で読み込み、保存する

PDFファイルを扱う場合、ファイルシステムから直接読み書きすることが可能ですが、特定の状況では、バイト列（byte string）やバイト配列（byte array）を使用してPDF文書を読み込み、保存する方が効率的です。この方法は、データ処理の柔軟性を高め、メモリ上で直接PDFを操作できるだけでなく、セキュリティの強化やアプリケーション間やネットワークでのデータ転送も容易にします。
この記事では、**Pythonを使用してバイト列やバイト配列を介してPDF文書を読み込み、保存する方法**を紹介します。

- **[PDF文書を作成し、バイト列またはバイト配列として保存](#pdf文書を作成しバイト列またはバイト配列として保存)**
- **[バイト列またはバイト配列からPDF文書を読み込んで操作](#バイト列またはバイト配列からpdf文書を読み込んで操作)**

この記事で使用する手法には、[Spire.PDF for Python](https://jp.e-iceblue.com/download/spire-pdf-for-python.html)を使用します。PyPI: `pip install Spire.PDF`

[無料ライセンスの申請](https://www.e-iceblue.com/TemLicense.html)

## PDF文書を作成し、バイト列またはバイト配列として保存
ライブラリ内のクラスとメソッドを使って直接PDF文書を作成し、`Stream`オブジェクトに保存できます。このオブジェクトは`Stream.ToArray()`メソッドで不変の`bytes`オブジェクトに変換可能です。さらに、この`bytes`オブジェクトを可変の`bytearray`オブジェクトに変換することで、バイトレベルの編集やその他の操作が行えます。以下は操作手順です。
1. 必要なモジュールをインポートします。
2. `PdfDocument`オブジェクトを作成します。
3. PDFページを設定し、ページを追加して内容を描画します。
4. `PdfDocument.SaveToStream()`メソッドを使用してPDF文書を`Stream`オブジェクトに保存します。
5. `Stream.ToArray()`メソッドで`Stream`オブジェクトを`bytes`オブジェクトに変換します。
6. `bytes`オブジェクトから直接`bytearray`オブジェクトを構築できます。
7. バイト列やバイト配列を使用して、ファイルへの書き込みやデータ転送など、さらなる操作が可能です。

**コード例**
```python
from spire.pdf import *

# PdfDocumentクラスのインスタンスを作成
pdf = PdfDocument()

# ドキュメントのページサイズと余白を設定
pageSettings = pdf.PageSettings
pageSettings.Size = PdfPageSize.A4()
pageSettings.Margins.Top = 50
pageSettings.Margins.Bottom = 50
pageSettings.Margins.Left = 40
pageSettings.Margins.Right = 40

# ドキュメントに新しいページを追加
page = pdf.Pages.Add()

# ドキュメントの内容用にフォントとブラシを作成
titleFont = PdfTrueTypeFont("Yu Gothic UI", 16.0, PdfFontStyle.Bold, True)
titleBrush = PdfBrushes.get_Brown()
contentFont = PdfTrueTypeFont("Yu Gothic UI", 13.0, PdfFontStyle.Regular, True)
contentBrush = PdfBrushes.get_Black()

# ページにタイトルを描画
titleText = "AI技術の基礎"
titleSize = titleFont.MeasureString(titleText)
page.Canvas.DrawString(titleText, titleFont, titleBrush, PointF(0.0, 30.0))

# ページに本文を描画
contentText = ("AI（人工知能）は、コンピュータシステムが人間の知能を模倣する能力を指します。"
               "AI技術は、機械学習、自然言語処理、コンピュータビジョンなどの分野で活用されており、"
               "さまざまな産業で自動化や効率化を進めています。AIの進化により、"
               "医療、金融、製造業など多くの分野での応用が急速に広がっています。")
# 本文の文字列フォーマットを設定
contentFormat = PdfStringFormat()
contentFormat.Alignment = PdfTextAlignment.Justify
contentFormat.LineSpacing = 20.0
# 本文のTextWidgetオブジェクトを作成し、文字列フォーマットを適用
textWidget = PdfTextWidget(contentText, contentFont, contentBrush)
textWidget.StringFormat = contentFormat
# TextLayoutオブジェクトを作成し、レイアウトオプションを設定
textLayout = PdfTextLayout()
textLayout.Layout = PdfLayoutType.Paginate
textLayout.Break = PdfLayoutBreakType.FitPage
# ページにTextWidgetを描画
rect = RectangleF(PointF(0.0, titleSize.Height + 50.0), page.Canvas.ClientSize)
textWidget.Draw(page, rect, textLayout)

# PDFドキュメントをStreamオブジェクトに保存
pdfStream = Stream()
pdf.SaveToStream(pdfStream)

# Streamオブジェクトをbytesオブジェクトに変換
pdfBytes = pdfStream.ToArray()

# Streamオブジェクトをbytearrayオブジェクトに変換
pdfBytearray = bytearray(pdfStream.ToArray())

# バイト配列をファイルに書き込む
with open("output/AI技術の基礎.pdf", "wb") as f:
    f.write(pdfBytearray)
```

結果
![ PDF文書を作成しバイト列またはバイト配列として保存](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/ec09a4ad-5cf7-f469-fdcf-c332308958a2.png)

## バイト列またはバイト配列からPDF文書を読み込んで操作
`Stream`クラスは、`bytes`オブジェクト（または`bytearray`から変換された`bytes`オブジェクト）を使用してインスタンスを直接構築することができます。そして、`PdfDocument.LoadFromStream()`メソッドで`Stream`オブジェクトをPDF文書として読み込み、編集や変換などの操作が可能です。以下は操作手順です。
1. 必要なモジュールをインポートします。
2. `bytes`オブジェクトを作成するか、既存の`bytes`オブジェクトを使用して`Stream`オブジェクトを構築します。
3. `PdfDocument`オブジェクトを作成します。
4. `PdfDocument.LoadFromStream()`メソッドを使用して`Stream`オブジェクトをPDF文書として読み込みます。
5. 文書に対して、ページのテキスト抽出などの操作を行います。

**コード例**
```python
from spire.pdf import *

# PDFファイルからバイト配列を作成
with open("Sample.pdf", "rb") as f:
    byteData = f.read()

# バイト配列からStreamオブジェクトを作成
stream = Stream(byteData)

# StreamオブジェクトをPDFドキュメントとして読み込む
pdf = PdfDocument(stream)

# 最初のページからテキストを取得
page = pdf.Pages.get_Item(0)
textExtractor = PdfTextExtractor(page)
extractOptions = PdfTextExtractOptions()
extractOptions.IsExtractAllText = True
text = textExtractor.ExtractText(extractOptions)

# テキストを出力
print(text)
```

結果
![バイト列またはバイト配列からPDF文書を読み込んで操作](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/58554bd5-78e3-2862-f48c-e1449c19c4a4.png)

この記事では、Pythonを使用してバイト列やバイト配列を介してPDF文書を読み込んだり保存したりする方法を紹介しました。

さらにPDF文書の操作方法については、[Spire.PDF for Pythonのチュートリアル](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Spire.PDF-for-Python-Program-Guide-Content.html)をご覧ください。