【问题标题】:c# Shorten int into case sensitive codec#将int缩短为区分大小写的代码
【发布时间】:2012-01-16 19:59:28
【问题描述】:

字母表中有 26 个字符 (abc..yz) 和 10 个数字 (0..9)。如果我们区分大小写,这为我们提供了 62 个字符的词典。

目前,我们正在根据数据库中的 ID 构建文件名的一部分。这些数字可能会变得很长,因此我们想缩短它们。例如,而不是:

file_459123.exe

我们宁愿:

file_aB5.exe

有没有人在 C# 中有一种方法可以将 int 转换为更短的区分大小写的字符串,并将区分大小写的字符串转换回 int?

示例(不一定是这种模式):

1 = 1
2 = 2
...
9 = 9
10 = a
11 = b
...
36 = z
37 = A

【问题讨论】:

  • 将 int 转换为字节;从大端删除零;通过base-64运行它...反向:通过base-64运行它;在大端用零填充;将字节转换为 int
  • 这适用于 Windows 吗? (几乎可以肯定,因为这个标记为 c#,asp.net)。如果是这样,请注意文件系统不区分大小写。这样做时,您实际上只有大写或小写字母,而不是两者。
  • 旁白:如果我不得不在 Windows 上管理大量文件,我会遇到大型目录的性能问题。我的解决方案是分解文件的标识号并将这些部分用于目录路径,例如Invoice_012345.pdf 将是 C:\HeapOStuff\01\23\ 中的一个文件。将目录限制为 100 个文件非常适合我的应用程序。
  • 我认为 ToString("x") 就足够了,因为使用 Base64(考虑到一个 int)你不会得到 much 更短的字符串,这些是 65535 //8= ffff 或对于 MaxInt ////fw== 7fffffff

标签: c# asp.net string encoding


【解决方案1】:

尽管有 Base64 引用,但这里有一个通用(非优化)解决方案:

// for decimal to hexadecimal conversion use this:
//var digits = "0123456789abcdef".ToCharArray();

var digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
             .ToCharArray();

int number = 459123;
string output = "";

do
{
    var digit = digits[(int)(number%digits.Length)];
    output = output.Insert(0, digit.ToString());
    number = (int)number/digits.Length;
}
while (number > 0);

// output is now "1Vrd"

【讨论】:

  • 如果数字只是一个字符串,而不是一个字符数组(你不需要),你可以用 number.Aggregate(0, (a, c) => a*digits.Length 转换回来+ 数字.IndexOf(c));
  • 其中 number = 使用您选择的任何方案编码的字符串 .. 例如“1Vrd”
  • 当有两个文件名“1vrd”和“1Vrd”时会发生什么?如果这是 Windows,我怀疑这是命名冲突。
  • 然后他将数字更改为他喜欢的任何唯一文件系统数字,以他喜欢的任何顺序......
【解决方案2】:

只是将 M4Ns 解决方案扩展到泛型类......

  public class BaseX
    {
        private readonly string _digits;

        public BaseX(string digits)
        {
            _digits = digits;
        }
        public string ToBaseX(int number)
        {           
            var output = "";
            do
            {                
                output = _digits[number % _digits.Length] + output;
                number = number / _digits.Length;
            }
            while (number > 0);
            return output;
        }

        public int FromBaseX(string number)
        {
            return number.Aggregate(0, (a, c) => a*_digits.Length + _digits.IndexOf(c));
        }
    }

然后你就可以...

var x = new BaseX("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
            Console.WriteLine(x.ToBaseX(10));
            Console.WriteLine(x.ToBaseX(459123));
            Console.WriteLine(x.ToBaseX(63));

            Console.WriteLine(x.FromBaseX("1Vrd"));
            Console.WriteLine(x.FromBaseX("A"));

            var bin = new BaseX("01");
            Console.WriteLine(bin.ToBaseX(10));

【讨论】:

    【解决方案3】:

    试试Base64

    【讨论】:

    • 您的链接转到 Microsoft Visual C++ 2008 Redistributable Package 页面。您可能希望更正它。
    • 对不起,会的。我在 iPad 上打字,但它不如旧键盘可靠。
    • Base64 不适用于 Windows 文件名 (NTFS/Fat),因为这些系统不区分大小写 - 请改用 base32,或选择一些不包括大小写的不同基本字符集相同的字母。 (某些 Url 案例也存在同样的问题 - 并非每个服务器都会尊重不同的大小写)。
    • @AlexeiLevenkov:没错.. OP 也没有意识到,因为他建议混合大小写。
    【解决方案4】:

    根据您的情况,您可能希望使用 Base32,因为受限制的字符集可能更易于阅读(即,一些用户无法轻松区分零和字母 o 之间的区别)。

    您可以找到示例herehere

    【讨论】:

    • +1:对于不区分大小写的文件系统,这比 base64 更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 2012-04-04
    • 2017-12-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多