1

通常のbase10番号として、おそらく大きな数値(UInt.MaxValue:18446744073709551615)を取得します。この番号は最終的にファイル名になります:12345678945768.txt

Windowsのファイル名は数字だけに限定されていないので、これをより短い文字列に「圧縮」したいと思いますが、文字列を数値にマップして戻すことができることを確認する必要があります。

小さい数値の場合:0001365555、hexedは他の何よりもはるかに短いです。私がこれまでに見つけたものはすべて、Base64が最短になると述べていますが、そうではありません。

これまで私はこれを試しました:

//18446744073709551615 - 20
UInt64 i = UInt64.MaxValue; // 0001365555

//"//////////8=" - 12
string encoded = Convert.ToBase64String(BitConverter.GetBytes(i)); 

//"FFFFFFFFFFFFFFFF" - 16
string hexed = i.ToString("X"); 

//"MTg0NDY3NDQwNzM3MDk1NTE2MTU=" - 28
string utf = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(i.ToString())); 

整数を「圧縮」して16進数と同様に変換するが、00-FFだけでなく00-zzを使用するより良い方法はありますか?

前もって感謝します!

4

5 に答える 5

4

私がこれまでに見つけたものはすべて、Base64が最短になると述べていますが、そうではありません。

Base64を使用したくない。Base64でエンコードされたテキストは/、Windowsのファイル名では許可されていない文字を使用できます。あなたは何か他のものを考え出す必要があります。

ほかに何か?

さて、あなたはあなた自身の基本変換を書くことができます、おそらくこのようなもの:

public static string Convert(ulong number)
{
    var validCharacters = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&()_-";
    char[] charArray = validCharacters.ToCharArray();
    var buffer = new StringBuilder();
    var quotient = number;
    ulong remainder;
    while (quotient != 0)
    {
        remainder = quotient % (ulong)charArray.LongLength;
        quotient = quotient / (ulong)charArray.LongLength;
        buffer.Insert(0, charArray[remainder].ToString());
    }
    return buffer.ToString();
}

これは「base-73」の結果です。の文字数が多いvalidCharactersほど、出力は小さくなります。ファイルシステムで正当な文字である限り、自由に追加してください。

于 2011-11-17T21:13:20.983 に答える
2

許可されている文字セットは何ですか?安全に使用できる7132種類のUnicode文字を識別できれば、64ビットの数値を5つのUnicode文字としてエンコードできます。一方、すべてのファイルシステムがそのような文字をサポートするわけではありません。139の有効な文字を識別できれば、データを9文字の文字列に圧縮できます。85では、10文字の文字列を使用できます。

于 2011-11-17T21:05:54.340 に答える
1

Base64を誤用しました。

(System.Text.Encoding.ASCII.GetBytes(i.ToString())

これにより、base10でエンコードされた整数を含むバイトシーケンスが生成され、base64で再度エンコードされます。それは明らかに非効率的です。

整数の生のバイトを取得し、base64でエンコードする必要があります。どのエンコーディングが最も効率的かは、許可する文字数によって異なります。翔が欲しいなら

また、配列の片側で0バイトをトリミングする必要があります。

var bytes=BitConverter.GetBytes(input);
int len=8;
for(int i=7;i>=0;i--)
{
  if(bytes[i]!=0)
  {
    len=i+1;
    break;
  }
}
string s=Convert.ToBase64String(bytes,0,len).ReplaceString('/','-');

これは、ビッグエンディアンシステムでは期待どおりに機能しないことに注意してください。

ただし、バイトエンコーディングをすべて一緒に使用することは避け、ベースの高い整数エンコーディングを使用する必要があります。

単純なバージョンは次のようになります。

string digitChars="0123..."
while(i!=0)
{
  int digit=i%digitChars.Length;
  i/=digitChars.Length;
  result=digitChars[digit]+result;
}
于 2011-11-17T21:03:59.023 に答える
0

実装は次のとおりです。非常に長い正の整数の基数変換

于 2011-11-17T21:09:10.410 に答える
0

上記のvcsjonesの回答を使用するコードがいくつかありますが、逆変換も含まれています。彼の答えのように、文字列のサイズを小さくするために必要な場合は、自由に文字を追加してください。以下の文字は、ulong.MaxValueの文字列サイズ13を生成します。

private const string _conversionCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

public static string UlongToCompressedString(ulong number)
{
    char[] charArray = _conversionCharacters.ToCharArray();
    var buffer = new System.Text.StringBuilder();
    var quotient = number;
    ulong remainder;
    do
    {
        remainder = quotient % (ulong)charArray.LongLength;
        quotient = quotient / (ulong)charArray.LongLength;
        buffer.Insert(0, charArray[remainder].ToString());
    } while (quotient != 0);
    return buffer.ToString();
}

public static ulong? CompressedStringToULong(string compressedNumber)
{
    if (compressedNumber == null)
        return null;

    if (compressedNumber.Length == 0))
        return 0;
    
    ulong result   = 0;
    int   baseNum  = _conversionCharacters.Length;
    ulong baseMult = 1;
    
    for (int i=compressedNumber.Length-1; i>=0; i--)
    {
        int cPos = _conversionCharacters.IndexOf(compressedNumber[i]);
        if (cPos < 0)
            return null;
        result += baseMult * (ulong)cPos;
        baseMult *= (ulong)baseNum;
    }

    return result;
}
于 2020-06-05T16:28:36.090 に答える