给定一个字符串转换为4字节块的十六进制... C#
我是一个初学者爱好者,并且一直在我的代码中研究一个问题。我的代码很丑陋,效率很低,主要是因为我缺乏经验。不过,我喜欢这个东西。给定一个字符串转换为4字节块的十六进制... C#
问题:给出一个字符串,我可以成功转换为十六进制。然而,我希望给定的字符串(尽管它的长度)被转换为十六进制的4字节块。对于字符串大于一个字节但小于4个字节的情况,我想在字符串的右侧填充“0”。我发现只有部分成功,只要我操作PadRight方法的totalWidth参数即可。我怎样才能达到我所追求的目标,而不需要额外的零碎块?
请看到确切的代码示例我使用下面:
// create a char array using the string provided to the encoder method
char[] arrayCharValues = strMessage.ToCharArray();
// create stringbuilder object
StringBuilder sb = new StringBuilder();
// iterate through each char and convert it to int32 then to Hex then append to stringbuilder object.
foreach (char c in arrayCharValues)
{
// convert char to int32
int intCharToNumVal = Convert.ToInt32(c);
// convert int32 to hex
string strNumToHexVal = String.Format("{0:X2}", intCharToNumVal);
// append hex value to string builder object
sb.Append(strNumToHexVal);
}
string s = sb.ToString();
if (s.Length % 8 == 0)
{
var list = Enumerable
.Range(0, s.Length/8)
.Select(i => s.Substring(i * 8, 8))
.ToList();
var res = string.Join(" ", list);
// DEBUG: echo results for testing.
Console.WriteLine("");
Console.WriteLine("String provided: {0}", strMessage);
Console.WriteLine("String provided total length: {0}", s.Length);
Console.WriteLine("Hex equivalent of string provided: {0}", sb.ToString());
Console.WriteLine("Hex in 8-digit chunks: {0}", res.ToString());
Console.WriteLine("======================================================");
}
else
{
int intDivisibleByEight = s.Length % 8;
int intPadRight = (8 - intDivisibleByEight)/2;
char pad = '0';
//BUG: doesn't know how to handle anything over 16 bits. If I use an input string of "coolsssss" i get 636F6F6C 73737373 73000000 00000000
//BUG: <cont'd> if i use the same input string and change the PadRight(32,pad) to PadRight(16,pad) i get 636F6F6C 73737373 and the final chunk is ignored.
//BUG: <cont'd> I want it to work as it does with the PadRight(32, pad) method but, I want it to ignore the all zeros chunk(s) that may follow.
//NOTE: int totalWidth = the number of characters i nthe resulting string, equal to the number of original characters plus any additional padding characters.
s = s.PadRight(32, pad);
var list = Enumerable
.Range(0, s.Length/8)
.Select(i => s.Substring(i * 8, 8))
.ToList();
var res = string.Join(" ", list);
// DEBUG: echo results for testing.
Console.WriteLine("");
Console.WriteLine("String provided: {0}", strMessage);
Console.WriteLine("String provided total length: {0}", s.Length);
Console.WriteLine("Hex equivalent of string provided: {0}", sb.ToString());
Console.WriteLine("Hex in 8-digit chunks: {0}", res.ToString());
Console.WriteLine("======================================================");
}
虽然所有这些.Range.Select很有趣,有时更容易恢复到简单的老的周期。分块结果不需要hexedString,我添加它只是为了显示不需要分块时的差异。
string strMessage = "coolsssss";
string hexedString = string.Join("", strMessage.Select(c => String.Format("{0:X2}", (int)c)))
.PadRight((strMessage.Length + 3)/4 * 8, '0');
StringBuilder sb = new StringBuilder(strMessage.Length * 9/4 + 10);
int count = 0;
foreach (char c in strMessage)
{
if (count == 4)
{
sb.Append(" ");
count = 0;
}
sb.Append(String.Format("{0:X2}", (int)c));
count++;
}
for (int i = 0; i < (4 - count) % 4; ++i)
{
sb.Append("00");
}
// DEBUG: echo results for testing.
Console.WriteLine("");
Console.WriteLine("String provided: {0}", strMessage);
Console.WriteLine("Hex equivalent of string provided: {0}", hexedString);
Console.WriteLine("Hex in 8-digit chunks: {0}", sb.ToString());
Console.WriteLine("======================================================");
编辑:
由于提问者@GabrielAlicea,我加了一些解释。
new StringBuilder(strMessage.Length * 9/4 + 10);
这基本上创建StringBuilder与内存预先分配到所需的大小。我们从4个字母加空格得到8位数字,这里9/4来自。加一些填充到四。计算并不准确,如果你愿意的话,你可以做到。预先分配动态增长的对象(如List,StringBuilder,Dictionary ...)是一种很好的习惯,如果您事先知道大小。列表例如在内部使用数组。填充后,它会获得两倍大小的数组,并将所有内容复制到其中。当你事先知道必要的尺寸时,这是浪费时间。使用StringBuilder它会更复杂(并取决于.net版本),但预分配无论如何都是个好主意。
(int i = 0; i < (4 - count) % 4; ++i)
计数是最后一个块中的字母数。我们为每个丢失的字母添加两个零,这意味着(4 - count)
次。它的工作原理除空字符串外,其中count
为0,(4 - count)
等于4.所以我加了% 4
来处理这个特定的情况。
你的代码,你可能想这样写:
int intPadRight = 8 - intDivisibleByEight;
这:
s = s.PadRight(s.Length + intPadRight, pad);
但你完全可以添加% 8
到intPadRight和消除if (s.Length % 8 == 0)
:
...
string s = sb.ToString();
int intDivisibleByEight = s.Length % 8;
int intPadRight = (8 - intDivisibleByEight) % 8;
char pad = '0';
s = s.PadRight(s.Length + intPadRight, pad);
var list = Enumerable
.Range(0, s.Length/8)
.Select(i => s.Substring(i * 8, 8))
.ToList();
var res = string.Join(" ", list);
// DEBUG: echo results for testing.
Console.WriteLine("");
Console.WriteLine("String provided: {0}", strMessage);
Console.WriteLine("String provided total length: {0}", s.Length);
Console.WriteLine("Hex equivalent of string provided: {0}", sb.ToString());
Console.WriteLine("Hex in 8-digit chunks: {0}", res.ToString());
Console.WriteLine("======================================================");
这正是我想要的。非常感谢你。你能告诉我在我的代码中我做错了什么吗?我正在寻找尽可能多的学习,因为我正在寻找指导。再次感谢! –
另外,当你实例化StringBuilder对象时,你能解释下面的内容吗? (strMessage。长度* 9/4 + 10)您还可以提供以下内容: (int i = 0; i
感谢您的解释! –
为什么不在你转换之前填充你的输入字符串?然后你的转换器函数可以假设所有的字符串都是(例如8)的倍数,你不必担心类似的代码分割。 –
感谢您的提示。我会尝试以下提供的示例。 –