Windowsのパス名を一意の整数に変換したい。
例えば:
パス名C:\ temp \ a.outの場合、すべての文字のASCII値を追加すると、1234になります。ただし、他のパスでも同じ番号を生成できます。では、さまざまなパス名に一意の番号を生成するための最良の方法は何ですか?
ハッシュ関数を調べてください。ハッシュを実行するときは、ほとんどの Windows ファイル名の大文字と小文字が区別されないという性質を考慮してください。
ほとんどの場合、使用している言語は、文字列 (またはデータのみ) のハッシュを取得できるライブラリ関数 (または関数のコレクション) を提供します。 SHA1は人気があり、衝突が少ないです。
ここStackoverflowには、ハッシュ関数に関する多くの質問があります。開始するには、「ハッシュ関数」を検索するだけです。これは、あなたの場合に役立つ SO の質問になる可能性があります:衝突率の低い 32 ビット整数になるパフォーマンスの高い文字列ハッシュ関数とは何ですか? .
整数よりも多くの可能なパス名があるため、真の一意性を持つことはできません。MD5 ハッシュのようなもので解決できます。
はい、入力のドメインが出力の範囲よりも大きいため、何らかのハッシュ関数を使用する必要があります。つまり、ほぼ確実に、ターゲット言語のデータ型で表現できる数値よりも多くの有効なパス名が存在します。
したがって、衝突を完全に回避することはできません。この保証がアプリケーションにとって不可欠である場合、整数への変換によってそれを行うことはできません。
このようなものはどうですか: ディレクトリレベルごとに (String->n ビット) のハッシュを使用します。10 のディレクトリ レベルのそれぞれに 20 ビットを割り当てることは、明らかにスケーリングにはなりませんが、最も低いディレクトリ レベルが最も多く使用されるという仮定の下では、ビットのテレスコーピング レベルになる可能性があります。
たとえば、(ルートから) /A/B/C/D/E/F がある場合、ある種の n ビット数を出力します。
ビット n/2 - n ハッシュ F
ビット n/4 - n/2 ビット ハッシュ E
n/8 - n/4 ビット ハッシュ D
などなど
「整数よりも多くの可能なパスがあるため、それらを格納することは不可能です」と言っているすべての人に:いいえ。ポスターは実装言語を指定していません。一部の言語は、任意の長さの整数をサポートしています。たとえば、Python。
他のコメントの1つで言及されている制限として、32,000文字のパスを使用するとします。パスで使用する256の異なる文字がある場合、次のようになります。
Python 2.5.1 (r251:54863, May 18 2007, 16:56:43)
[GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 32000L**256L
20815864389328798163850480654728171077230524494533409610638224700807216119346720596024478883464648369684843227908562015582767132496646929816279813211354641525848259018778440691546366699323167100945918841095379622423387354295096957733925002768876520583464697770622321657076833170056511209332449663781837603694136444406281042053396870977465916057756101739472373801429441421111406337458176000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L
>>>
Pythonがそれをうまく表現していることに注目してください。はい、おそらくそれを行うためのより良い方法がありますが、それはそれが不可能であるという意味ではありません。
編集: rjackは、実際には256 ^ 32000であり、その逆ではないと指摘しました。Pythonはまだそれをうまく処理します。パフォーマンスは、何かが望まれることを残すかもしれませんが、数学的に不可能であると言うのは間違っています。
整数よりも多くの可能なパス名があるため、真の一意性を持つことはできません。MD5 ハッシュのようなもので解決できます。
整数よりも多くのパス名が考えられるとは思いません。パス名から一意の番号を作成するための構造として、各文字を (2 桁の) 番号に変換できます (つまり、10-25,26=.、次に他の特殊文字、および 27 が / であることを前提としています)。異なる文字数が 89 未満の場合、3 桁のエンコードに移行できます)
home/nlucaroni/documents/cv.pdf
1724221427232130121027242318271324122827123136251315
これは全単射を形成します (ただし、有効なパス名だけを数えると、全射プロパティは失敗しますが、通常はその保持を気にしません) --整数ではないパスを考え出します。
この数値は明らかに 64 ビットの unsigned int (最大値は 18446744073709551615) に収まらないため、実用的ではありませんが、これは私の回答の要点ではありません。
ここで読むことができますC#で2つのパスが同じファイルを参照しているかどうかを判断する最良の方法 パスを一意に識別する方法. 3 つの数値 (dwVolumeSerialNumber、nFileIndexHigh、および nFileIndexLow) が必要です。おそらく、これら 3 つの数値を組み合わせて、ビット数が 3 倍の新しい数値にすることができます。ここも参照してください: C# のお気に入りの拡張メソッドは何ですか? (codeplex.com/extensionoverflow) .
これが Unix の場合は、その inode 番号を取得できます。ls -i コマンドラインで表示します。stat()コマンドを使用すると、プログラムから取得できます。
ソフト リンクは同じファイルとして表示されますが、ハード リンクは別のファイルとして表示されます。これは、必要な動作である場合とそうでない場合があります。
多くの人がハッシュについて話しているのを見ます。それは機能する可能性がありますが、理論的には、ハッシュがファイル名で許可されていない整数値を圧縮する以上のことを行う場合、衝突が発生する可能性があります. それが受け入れられない場合、ハッシュは常にファイル名とほぼ同じ桁数になります。その時点で、ファイル名をそのまま使用することもできます。