如何在 C# 中复制 Perl 的解包功能?

Posted

技术标签:

【中文标题】如何在 C# 中复制 Perl 的解包功能?【英文标题】:How can I replicate Perl's unpack functionality in C#? 【发布时间】:2008-10-08 11:28:20 【问题描述】:

我正在尝试在 C# 中重新创建 Perl 脚本,但在创建目标系统所需的校验和值时遇到问题。

在 Perl 中,这个校验和是使用 unpack 函数计算的:

while (<PACKAGE>) 
    $checksum += unpack("%32C*", $_);

$checksum %= 32767;
close(PACKAGE);

其中PACKAGE 是.tar 文件输入流

我需要在 C# 中复制它,但找不到复制 unpack 函数的方法。

感谢所有帮助!

(我知道有更好的校验和计算可用,但无法更改目标系统,因此无法更改计算)

【问题讨论】:

【参考方案1】:

Mono 中似乎有一个名为DataConvert 的库,它的编写目的是提供类似于Perl 的打包/解包的功能。这能满足您的需要吗?

【讨论】:

OP 用这个问题向互联网发送了垃圾邮件。显然他不是在寻找答案,因为我已经在 CodeProject 上向他提出了你的建议。 不幸的是,我无法在我们使用的服务器上安装 dataconvert 库,因此我正在寻找替代方案。我不会说在 7 个论坛上问这个问题是在向互联网发送垃圾邮件——我的假设是每个论坛会有不同的读者,我会从每个论坛得到不同的回复。..【参考方案2】:

Perkl 的解包描述为 here 和 here。从此,您应该能够在 C# 中编写等价的代码。

【讨论】:

【参考方案3】:

为了补充 Mitch Wheat 的评论,这里有一个 Java 实现(它只执行一个块)。我相信您会找到一种方法将其转换为 C#,并执行多个块。

int sum = 0;
for (byte b : buffer) 
    sum += (int) b & 255;

return sum % 32767;

希望这会有所帮助!

【讨论】:

【参考方案4】:

在我在这里的测试中,使用 %32C 解包似乎是字节的加法总和,限制为 32 位。

print unpack("%32C*", 'A');
65
print unpack("%32C*", 'AA');
130

复制它应该不难。

【讨论】:

是的,我似乎遇到的问题是因为该文件是一个 tar,其中包含非标准的 ascii 字符,这些在 perl 脚本和我放在一起的 C# 脚本中会产生不同的结果。只是无法确定原因。 你在这两种情况下都确保二进制模式吗?无论文件格式是什么“tar”类型,以二进制(非翻译或非 ASCII)模式一次读取一个字节应该给出相同的字节,而不管语言如何。【参考方案5】:

基于Chris Jester-Young和piCookie的cmets,我开发了如下函数。我希望你觉得它有用。

int fileCheckSum(const char *fileName)

   FILE *fp;
   long fileSize;
   char *fileBuffer;
   size_t result;
   int sum = 0;
   long index;

   fp = fopen(fileName, "rb");
   if (fp == NULL)
   
      fputs ("File error",stderr); 
      exit (1);
   

   fseek(fp, 0L, SEEK_END);
   fileSize = ftell(fp);
   fseek(fp, 0L, SEEK_SET);

   fileBuffer = (char*) malloc (sizeof(char) * fileSize);   
   if (fileBuffer == NULL)
   
      fputs ("Memory error",stderr);
      exit (2);
   

   result = fread(fileBuffer, 1, fileSize, fp);   
   if (result != fileSize)
   
      fputs ("Reading error", stderr);
      if (fileBuffer != NULL)
         free(fileBuffer);

      exit (3);
   

   for (index = 0; index < fileSize; index++)
   
      sum += fileBuffer[index] & 255;
   

   fclose(fp);
   if (fileBuffer != NULL)
      free(fileBuffer);

   return sum % 32767;  

【讨论】:

以上是关于如何在 C# 中复制 Perl 的解包功能?的主要内容,如果未能解决你的问题,请参考以下文章

“W”在 Perl 的解包函数中究竟做了啥?

C#中Python的解包函数

如何在 Perl 中使用“打包/解包”?

python的解包操作符*和**是如何使用的?

解包函数将如何在 perl 中用于此代码 $str =~ s/([^\w ])/'%'.unpack('H2', $1)/eg;

如何从二进制文件中读取块并使用 Python 或 Perl 解包提取结构?