文字化け対策で最初にすることは、見た目を直すことではなく、元ファイルの文字コードと改行を特定することです。epub形式 作り方を安全に進めるなら、変換前の原稿、別名で保存した原稿、そこから生成したEPUBを別々に確認します。今回の固定標本では、Shift_JIS・LFの三行36文字を、別名のUTF-8・LFファイルへ変換しました。再読込後も36文字で、生成EPUBの検査はvalid=true、問題0件でした。
ここで確かめたのはファイルと生成物です。Rune Studioの画面で変換不能文字が赤く見えたか、自動保存が止まったかは操作していません。CLIの成功から画面表示を推測せず、原稿を失わないための順序と、利用者が最後に確認するUI項目を分けて説明します。
元原稿を上書きせず文字コードを読む
検証入力はlegacy-source-sjis.txtです。三行で、「STUDIO-403 編集用原稿」という見出しと「夜風と水面を確認する合成文です。」という本文を持ちます。rune inspect text --file legacy-source-sjis.txt --jsonで読み取った値は、encoding=Shift_JIS、lineEnding=LF、characterCount=36、lineCount=3でした。変換不能文字の配列は空です。
大切なのは、ファイルを開いた瞬間にUTF-8だと決めつけないことです。代替文字が表示された状態で保存すると、元のバイト列へ戻せなくなる恐れがあります。検査中は原稿を読み取り専用の入力として扱い、パス、SHA-256、検出文字コード、改行、文字数を控えます。表示が自然に見えるかどうかは補助情報にとどめます。
UTF-8版は別名で作る
変換にはiconv -f SHIFT_JIS -t UTF-8 legacy-source-sjis.txt -o repaired-utf8.mdを使いました。出力先をrepaired-utf8.mdという別名にしたため、元のShift_JISファイルは比較対象として残ります。変換後ファイルは78バイト、SHA-256は5d53dad03fe7c9ef64e466517a5e45d629d3238849ec6bc460ff2646c70a357cでした。
同じ名前への上書きは避けます。誤った入力文字コードを指定しても、出力ファイルが作られる場合があるからです。別名なら、変換前後を並べ、見出し、本文、行数、句読点を照合できます。本番原稿へ採用するのは、後続の再読込が合格してからです。
36文字とLFが保たれたか再読込する
別名版にもう一度rune inspect text --file repaired-utf8.md --jsonを実行しました。結果はencoding=UTF-8、lineEnding=LF、characterCount=36、lineCount=3、unconvertible=[]です。文字コードは意図どおり変わり、改行、文字数、行数は変わっていません。この組み合わせが今回の変換受入値です。
文字数だけが同じでも十分ではありません。別の文字へ置換されても一文字として数えられるため、二行の本文を実際に照合します。逆に、バイト数が57から78へ変わること自体は失敗ではありません。Shift_JISとUTF-8は同じ日本語でも必要なバイト数が異なります。比較する層を、バイト、文字、行、内容に分けると誤判定を防げます。
変換失敗は元原稿に戻って直す
入力指定を誤る、出力が0バイトになる、文字数が36から変わる、代替文字が混ざる。このいずれかが起きたら、別名版を本番へ進めません。失敗ファイルは削除せず、実行したコマンド、終了値、標準エラー、出力SHAを一組で残します。その後、元のlegacy-source-sjis.txtを再度検査し、検出値と-f SHIFT_JISが一致しているかを確かめます。
復旧では、壊れた出力を手で直して続行するのではなく、正しい入力から新しい別名版を作ります。そしてUTF-8、LF、36文字、三行、変換不能0件を最初から読み直します。このやり直し方なら、どのファイルが正本かを見失わず、失敗の原因も後から追えます。
合格したUTF-8版だけをEPUBへ渡す
固定試行ではrepaired-utf8.mdだけを章として選択し、シリーズ情報と巻情報を設定してEPUBを生成しました。出力はstudio-403-260903.100000.epub、SHA-256はb0a767edda849615767a91550587f578e57bf636e8a44cadeb0ac144d504364cです。ZIPとして開くと九エントリを持ち、本文はp001.xhtmlに収録されています。
保存後のrune inspect epub --path ... --jsonはvalid=true、issues=[]でした。固定証拠では文字欠落0件として記録されています。ここでの結論は、別名UTF-8版から作ったこのEPUBにローカル検査上の問題がなかった、という範囲です。販売ストアやすべてのReaderで同じ表示になることまでは保証しません。
赤表示と自動保存は利用者が画面で確認する
公開資料には、変換不能文字の警告表示や保存に関わる機能が説明されています。ただし今回の操作記録に、赤表示の位置、件数、警告文、自動保存停止のタイミングはありません。したがって「赤く表示された」「自動保存が止まった」とは書けません。アプリ版、開いたファイル、保存前SHA、警告の文字列、保存後SHAを持つ別のUI試験が必要です。
利用者確認では、まず元ファイルのコピーを開き、検出文字コードを表示します。警告対象がある標本なら、赤表示の範囲と検出一覧の位置が一致するかを確認します。次に自動保存が行われていないことをディスクSHAで読み、明示保存後の変化を記録します。今回の36文字標本はunconvertible=[]なので、警告が出ない正常系の確認に使い、警告の見え方は専用の負の標本へ分けます。
三つの受入票で文字化けを持ち越さない
最終引き渡しは三枚に分けます。入力票にはShift_JIS、LF、36文字、三行、元SHAを記載します。変換票には実コマンド、別名パス、UTF-8、LF、36文字、三行、変換不能0件を記載します。EPUB票には生成元パス、EPUB SHA、valid=true、issues=[]、欠落0件を記載します。どれか一枚でも値が欠けたら完了扱いにしません。
赤表示、自動保存停止、Readerでの見た目は第四のUI票に残します。この票は未実測のままです。ファイル変換とEPUB検査が合格しても、UI欄を自動的に合格へ変えないことが境界です。元原稿を保存し、別名版を再読込し、その版だけからEPUBを作る。この順序が、文字化けを次の工程へ持ち越さないための実用的な作り方です。


