2

ファイルキャッシュがあり、ファイルはさまざまな URL からダウンロードされています。各ファイルを URL の名前で保存したいと思います。ただし、これらの名前は非常に長くなる可能性があり、FAT32 ファイル システムを使用するデバイスを使用しているため、実際のディスク スペースがなくなる前に、長い名前がリソースを食い尽くしてしまいます。

ファイル名を短くする方法を探しています。文字列をハッシュするための提案を受けました。しかし、ハッシュが 2 つの異なる文字列に対して一意であることが保証されているかどうかはわかりません。ハッシュ化された 2 つの URL が同じハッシュ値である場合に、誤って間違った画像をフェッチしてしまうと大変なことになります。

ありがとう

4

7 に答える 7

5

URL ごとにUUIDを生成し、それをファイル名として使用できます。

UUID は一意 (または「実質的に一意」) で、長さは 36 文字であるため、ファイル名は問題にならないと思います。

バージョン 5 の時点で、JDK には UUID (java.util.UUID) を生成するクラスが同梱されています。UUID を URL に関連付ける方法がある場合は、UUID をランダムに生成するか、名前ベースの UUID を使用できます。名前ベースの UUID は常に同じであるため、次のことが常に当てはまります。

String url = ...
UUID urlUuid = UUID.nameUUIDFromBytes(url.getBytes);
assertTrue(urlUuid.equals(UUID.nameUUIDFromBytes(url.getBytes)));
于 2011-09-01T20:21:41.957 に答える
3

入力ごとに異なるハッシュを保証できる(短縮)ハッシュはありません。それは単に不可能です。

私が通常行う方法は、キャッシュファイルの先頭(たとえば、最初の行)に元の名前を保存することです。したがって、キャッシュ内のファイルを見つけるには、次のようにします。

  • URLをハッシュする
  • そのハッシュに対応するファイルを検索します
  • 最初の行を確認してください。完全なURLと同じ場合:
  • ファイルの残りの部分は2行目以降のものです

URL->ファイルマッピングをデータベースに保存することも検討できます。

于 2011-09-01T18:52:24.697 に答える
2

しかし、ハッシュが 2 つの異なる文字列に対して一意であることが保証されているかどうかはわかりません。

それらは非常にそうではありません(鳩の巣の原理により、そうではありません)。しかし、ハッシュが十分に長く (少なくとも 64 ビット)、適切に分散されている (理想的には暗号化ハッシュ) 場合、衝突の可能性は非常に小さくなるため、心配する必要はありません。

大まかなガイドラインとして、ファイルの数が可能な異なるハッシュの数の平方根に近づくと、衝突が発生する可能性が高くなります (誕生日のパラドックス)。したがって、64 ビット ハッシュ (10 文字のファイル名) の場合、40 億個のファイルがある場合、約 50% の確率で 1 回の衝突が発生します。

それが許容できるリスクかどうかを判断する必要があります。ハッシュを長くすることで衝突の可能性を減らすことができますが、もちろん、ある時点でそれはあなたが望むものとは反対のことを意味します.

于 2011-09-01T18:56:39.710 に答える
1

現在、SHA-1アルゴリズムが推奨されています。このアルゴリズムの衝突を意図的に誘発する既知の方法はないため、安全である必要があります。共通の構造(プレフィックスなど)を持つ2つのデータとの衝突を引き起こすことhttp://はさらに困難です。HTTP 200応答を取得した後でこのようなものを保存すると、URLは明らかに何かをフェッチしたため、同じSHA-1ハッシュで2つの異なる有効なURLを取得することは実際には問題になりません。

安心できる場合は、Gitがそれを使用して、ソースコードリポジトリ内のすべてのオブジェクト、コミット、フォルダーを識別します。オブジェクトストアで衝突した人のことはまだ聞いたことがありません。

于 2011-09-01T18:52:28.463 に答える
1

ハッシュが一意であるとは限りませが、衝突の可能性はほとんどありません。

たとえば、ハッシュが 128 ビットの場合、エントリのペアが衝突する可能性は 2^128 分の 1 です。誕生日のパラドックスにより、テーブルに 10^18 のエントリがあった場合、衝突の可能性はわずか 1% であるため、実際に心配する必要はありません。あなたが過度に偏執的である場合は、SHA256 または SHA512 を使用してハッシュのサイズを増やしてください。

明らかに、ハッシュ表現が実際に元のファイル名よりも少ないスペースを占有することを確認する必要があります。Base-64 でエンコードされた文字列は 1 文字あたり 6 ビットを表すため、最初にハッシュを実行する価値があるかどうかを計算することができます。

名前が長すぎるためにファイル システムが barfs する場合は、実際のストレージ用にプレフィックス サブディレクトリを作成できます。たとえば、ファイルがハッシュ ABCDE をマップする場合、それを として保存する/path/to/A/B/CDE/path/to/ABC/DE、ファイル システムに最適なものに応じて保存できます。

Git は、実際のこの手法の良い例です。

于 2011-09-01T18:53:09.090 に答える
1

あなたができることは、ファイルをインデックスで保存し、インデックスファイルを使用して実際のファイルの場所を見つけることです

あなたが持っているディレクトリに:

index.txt
file1
file2
...
etc.

index.txt では、いくつかのデータ構造を使用してファイル名を効率的に検索します (または DB に置き換えます)。

于 2011-09-01T18:53:55.320 に答える
0

私のコメントを見てください。
考えられる解決策の 1 つ (多数あります) は、ローカル ファイル (SQLite? XML? TXT?) を作成し、そこにペア (file_id - file_name) を保存して、ダウンロードしたファイルを一意の ID でファイル名として保存できるようにすることです。
単なるアイデアであり、最高ではありません...

于 2011-09-01T18:52:46.930 に答える