PHP開発では、 MD5_FILE()は、ファイルコンテンツのハッシュ値を生成するために一般的に使用される関数です。開発者は通常、それを使用して、ファイルが変更されたかどうかを確認するか、ファイルの整合性を確認します。ただし、多くの開発者は、この関数を使用する際に一見「不可解な」問題に遭遇します。異なるエンコーディング環境でMD5_File()を使用して得られるハッシュ値は異なります。
これは直感に反するようですが、その背後には明確な技術的理由があります。この記事では、この状況がエンコーディングの観点から発生する理由を探ります。
まず、 md5_file()の本質を理解する必要があります。
$hash = md5_file('/path/to/file.txt');
この関数は、ファイル全体の元のバイナリデータを読み取り、MD5値を計算します。したがって、人間の読み取り可能なテキストではなく、ファイルバイトコンテンツ自体に焦点を当てています。
つまり、視覚的に表示されたテキストがファイル内のバイトの変更とまったく同じであっても、MD5値は異なります。
一般的な誤解は、コンテンツが同じ場合、同じMD5値を取得する必要があることです。実際には:
キャラクター「ミディアム」は、UTF-8: 0xe4 0xb8 0xadの3バイトです
GBKでは、 0xd6 0xd0の2バイトです
2つのファイルがある場合、1つはUTF-8エンコードで、もう1つはGBKエンコードです。これは「中国のテスト」と書かれていますが、 MD5_File()を読んだ後、基礎となるバイトストリームが異なり、自然なハッシュ値も異なります。
開発者は、多くの場合、編集者にPHPまたはテキストファイルを書きます。エディターがデフォルトで(BOMの有無にかかわらず)UTF-8として保存するか、ANSI/GBKとして保存すると、ファイルの実際のバイトストリームが一貫していません。
たとえば、Windowsメモ帳にファイルを保存することは、デフォルトでANSIエンコードです。 VSコードでの保存中は、デフォルトではBOM-LESSです。 2つのファイルの内容は同じように見えますが、次のコードを介して次のように見えます。
echo md5_file('file-ansi.txt') . "\n";
echo md5_file('file-utf8.txt') . "\n";
さまざまなハッシュ出力が表示されます。
M66.netに次のPHPスクリプトを展開するとします。
$file1 = 'https://m66.net/files/utf8.txt'; // UTF-8 コーディング
$file2 = 'https://m66.net/files/gbk.txt'; // GBK コーディング
echo 'UTF-8: ' . md5_file($file1) . "\n";
echo 'GBK: ' . md5_file($file2) . "\n";
実行の結果は、2つのMD5値が異なることを明確に示します。
ユニファイドエンコード形式:プロジェクトの唯一のエンコード形式としてのUTF-8(BOMなし)の強制使用が最も簡単で最も効果的な方法です。
ファイルを保存する前にエンコーディングを変換します。ICONVやMB_CONVERT_ENCODING()などのツールを使用して、ファイルの内容を統合形式に変換します。
例えば:
$content = file_get_contents('file.txt');
$content = mb_convert_encoding($content, 'UTF-8', 'GBK');
file_put_contents('converted.txt', $content);
エディタの設定の確認:使用しているIDEまたはテキストエディタが、一貫したデフォルトのエンコード形式を設定していることを確認してください。
md5_file()はファイルの元のバイトストリームに依存し、エンコーディングの違いは計算結果に影響します。これを理解することは、多言語およびマルチプラットフォームのファイルコンテンツを扱うために重要です。実際のプロジェクトでは、常にファイルエンコードを一貫性に保つことは、ハッシュ検証の有効性を確保するための重要な尺度です。