iTextSharpを使用してPDFファイルからテキストを読み取ります。ただし、PDFファイルには画像しか含まれていないため、テキストを抽出できない場合があります。同じPDFファイルを毎日ダウンロードしていますが、PDFが変更されていないか確認したいと思います。テキストと変更日を取得できない場合、MD5チェックサムはファイルが変更されたかどうかを確認する最も信頼できる方法ですか?
もしそうなら、私は暗号化の経験があまりないので、いくつかのコードサンプルがありがたいです。
iTextSharpを使用してPDFファイルからテキストを読み取ります。ただし、PDFファイルには画像しか含まれていないため、テキストを抽出できない場合があります。同じPDFファイルを毎日ダウンロードしていますが、PDFが変更されていないか確認したいと思います。テキストと変更日を取得できない場合、MD5チェックサムはファイルが変更されたかどうかを確認する最も信頼できる方法ですか?
もしそうなら、私は暗号化の経験があまりないので、いくつかのコードサンプルがありがたいです。
回答:
System.Security.Cryptography.MD5を使用すると、非常に簡単です。
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return md5.ComputeHash(stream);
}
}
(実際に使用されているMD5実装は破棄する必要がないと思いますが、おそらくそれでも破棄するでしょう)。
後で結果を比較する方法はあなた次第です。たとえば、バイト配列をbase64に変換したり、バイトを直接比較したりできます。(配列はをオーバーライドしないことに注意してくださいEquals
。base64を使用する方が簡単ですが、ハッシュの比較だけに関心がある場合は少し効率が悪くなります。)
ハッシュを文字列として表す必要がある場合は、次を使用してハッシュを16進数に変換できますBitConverter
。
static string CalculateMD5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
BitConverter.ToString(md5.ComputeHash(stream)).Replace("-","").ToLower();
.Replace("-", String.Empty)
より良いアプローチだと思います。ユーザー入力とファイルハッシュを比較したときに誤った結果が得られたため、1時間のデバッグセッションを行いました。
これが私のやり方です:
using System.IO;
using System.Security.Cryptography;
public string checkMD5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return Encoding.Default.GetString(md5.ComputeHash(stream));
}
}
}
using
ファイルを開くと失敗する可能性が高いので、ブロックの交換が役立つと思います。フェイルアーリー/ファストアプローチは、このようなシナリオでMD5インスタンスを作成(および破棄)するために必要なリソースを節約します。また、最初の括弧を省略して、using
読みやすさを失わずにインデントのレベルを保存できます。
私はこの質問がすでに回答されていることを知っていますが、これは私が使用するものです:
using (FileStream fStream = File.OpenRead(filename)) {
return GetHash<MD5>(fStream)
}
GetHashの場所:
public static String GetHash<T>(Stream stream) where T : HashAlgorithm {
StringBuilder sb = new StringBuilder();
MethodInfo create = typeof(T).GetMethod("Create", new Type[] {});
using (T crypt = (T) create.Invoke(null, null)) {
byte[] hashBytes = crypt.ComputeHash(stream);
foreach (byte bt in hashBytes) {
sb.Append(bt.ToString("x2"));
}
}
return sb.ToString();
}
おそらく最善の方法ではありませんが、便利な場合があります。
public static String GetHash<T>(this Stream stream) where T : HashAlgorithm, new() { StringBuilder sb = new StringBuilder(); using (T crypt = new T()) { byte[] hashBytes = crypt.ComputeHash(stream); foreach (byte bt in hashBytes) { sb.Append(bt.ToString("x2")); } } return sb.ToString(); }
これが私が見つけた少しシンプルなバージョンです。ファイル全体を一度に読み取り、1つのusing
ディレクティブのみが必要です。
byte[] ComputeHash(string filePath)
{
using (var md5 = MD5.Create())
{
return md5.ComputeHash(File.ReadAllBytes(filePath));
}
}
ReadAllBytes
、ファイル全体を単一の配列にロードすることです。これは、2 GiBを超えるファイルではまったく機能せず、中サイズのファイルでもGCに大きな負荷をかけます。ジョンの答えは少しだけ複雑ですが、これらの問題に悩まされることはありません。だから私はあなたの答えより彼の答えを好む。
using
最初の波括弧using (var md5 = MD5.Create()) using (var stream = File.OpenRead(filename))
を付けずにsを続けて配置すると、不要なインデントなしで行ごとに使用できます。
using
ディレクティブのみを必要とする」ということでした。すべてをメモリに読み込むのは、本当に良い理由ではありませんでした。より効果的なアプローチは、データをにストリーミングすることComputeHash
です。可能なusing
場合にのみ使用する必要がありますが、余分なレベルのインデントを避けたいかどうかは完全に理解できます。
私はパーティーに遅れるが、実際にソリューションを実装する前にテストを実行したことを知っています。
組み込みのMD5クラスとmd5sum.exeに対してもテストを行いました。私の場合、組み込みのクラスは13秒かかりましたが、実行ごとにmd5sum.exeが約16〜18秒かかりました。
DateTime current = DateTime.Now;
string file = @"C:\text.iso";//It's 2.5 Gb file
string output;
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(file))
{
byte[] checksum = md5.ComputeHash(stream);
output = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();
Console.WriteLine("Total seconds : " + (DateTime.Now - current).TotalSeconds.ToString() + " " + output);
}
}
MD5を計算してAzure BLOBのMD5と一致するかどうかを確認する必要がある場合は、このSOの質問と回答が役立つ可能性があります。AzureにアップロードされたBLOBのMD5ハッシュがローカルコンピューター上の同じファイルと一致しません