C#相当于perl`pack(";v";,value)`而将一些值打包到`byte[]`
我试图在我的c代码中复制perl脚本的行为。当我们将任何值转换为C#相当于perl`pack(";v";,value)`而将一些值打包到`byte[]`,c#,perl,byte,bytearray,bytecode,C#,Perl,Byte,Bytearray,Bytecode,我试图在我的c代码中复制perl脚本的行为。当我们将任何值转换为字节[]时,无论使用何种语言,其外观都应该相同。所以 我有一个函数调用,在perl中看起来像这样: $diag\u cmd=pack(“V”,长度($s\u部分))$s_部分 其中,$s_par在以下函数中定义。它正在获取.pds文件的位置C:\Users\C\u desaik\Desktop\DIAG\PwrDB\offtarget\data\get\u 8084\u gpio.pds $s_part = sub re
字节[]
时,无论使用何种语言,其外观都应该相同。所以
我有一个函数调用,在perl中看起来像这样:
$diag\u cmd=pack(“V”,长度($s\u部分))$s_部分代码>
其中,$s_par
在以下函数中定义。它正在获取.pds
文件的位置C:\Users\C\u desaik\Desktop\DIAG\PwrDB\offtarget\data\get\u 8084\u gpio.pds
$s_part =
sub read_pds
{
my $bin_s;
my $input_pds_file = $_[0];
open(my $fh, '<', $input_pds_file) or die "cannot open file $input_pds_file";
{
local $/;
$bin_s = <$fh>;
}
close($fh);
return $bin_s;
}
但是结果字节数组看起来不一样。我是否必须遵循任何特殊机制来复制pack(“V”,length($s_part))的行为$s_部分
?正如Simon Whitehead提到的,模板字符V
告诉pack
将值打包为无符号长(32位)整数(以小尾端顺序)。因此,您需要将字节转换为无符号整数列表(或数组)
例如:
static uint[] UnpackUint32(string filename)
{
var retval = new List<uint>();
using (var filestream = System.IO.File.Open(filename, System.IO.FileMode.Open))
{
using (var binaryStream = new System.IO.BinaryReader(filestream))
{
var pos = 0;
while (pos < binaryStream.BaseStream.Length)
{
retval.Add(binaryStream.ReadUInt32());
pos += 4;
}
}
}
return retval.ToArray();
}
更新
如果要读取一个长度前缀字符串或它们的列表,可以使用此函数:
var list = UnpackUint32(@"C:\Users\c_desaik\Desktop\DIAG\PwrDB\offtarget\data\get_8084_gpio.pds");
private string[] UnpackStrings(string filename)
{
var retval = new List<string>();
using (var filestream = System.IO.File.Open(filename, System.IO.FileMode.Open))
{
using (var binaryStream = new System.IO.BinaryReader(filestream))
{
var pos = 0;
while ((pos + 4) <= binaryStream.BaseStream.Length)
{
// read the length of the string
var len = binaryStream.ReadUInt32();
// read the bytes of the string
var byteArr = binaryStream.ReadBytes((int) len);
// cast this bytes to a char and append them to a stringbuilder
var sb = new StringBuilder();
foreach (var b in byteArr)
sb.Append((char)b);
// add the new string to our collection of strings
retval.Add(sb.ToString());
// calculate start position of next value
pos += 4 + (int) len;
}
}
}
return retval.ToArray();
}
private string[]解压字符串(字符串文件名)
{
var retval=新列表();
使用(var filestream=System.IO.File.Open(filename,System.IO.FileMode.Open))
{
使用(var binaryStream=new System.IO.BinaryReader(filestream))
{
var-pos=0;
而((位置+4)
也可以写成
pack("V/a*", $s_part)
创建长度前缀字符串。长度存储为32位无符号小尾数
+----------+----------+----------+----------+-------- ...
| Length | Length | Length | Length | Bytes
| ( 7.. 0) | (15.. 8) | (23..16) | (31..24) |
+----------+----------+----------+----------+-------- ...
以下是如何从字节中重新创建原始字符串:
读取4个字节
如果使用的机器不是little endian机器,
将字节重新排列为本机顺序
将这些字节转换为32位无符号整数
读取与该数字相等的字节数
将字节序列转换为字符串
有些语言提供的工具可以执行这些步骤中的一个以上
我不懂C#,所以我不能为您编写代码,但我可以用另外两种语言给您举个例子
在Perl中,这将编写如下:
sub read_bytes {
my ($fh, $num_bytes_to_read) = @_;
my $buf = '';
while ($num_bytes_to_read) {
my $num_bytes_read = read($fh, $buf, $num_bytes_to_read, length($buf));
if (!$num_bytes_read) {
die "$!\n" if !defined($num_bytes_read);
die "Premature EOF\n";
}
$num_bytes_to_read -= $num_bytes_read;
}
return $buf;
}
sub read_uint32le { unpack('V', read_bytes($_[0], 4)) }
sub read_pstr { read_bytes($_[0], read_uint32le($_[0])) }
my $str = read_pstr($fh);
在C中
int读取字节(文件*fh,无效*buf,大小\u t num\u字节\u至\u读取){
while(读取的字节数){
size\u t num\u bytes\u read=fread(buf,1,num\u bytes\u to\u read,fh);
如果(!num_bytes_read)
返回0;
num_bytes_to_read-=num_bytes_read;
buf+=读取的字节数;
}
返回1;
}
int read_uint32le(文件*fh,uint32_t*p_i){
int ok=读取字节(fh,p_i,sizeof(*p_i));
如果(!ok)
返回0;
{/*在非LE机器上重新排列字节*/
常量char*p=(char*)p_i;
*p_i=(((p[3]文件pack
似乎说V
等同于C#中的无符号32位(uint
)整数…而不是字节。
+----------+----------+----------+----------+-------- ...
| Length | Length | Length | Length | Bytes
| ( 7.. 0) | (15.. 8) | (23..16) | (31..24) |
+----------+----------+----------+----------+-------- ...
sub read_bytes {
my ($fh, $num_bytes_to_read) = @_;
my $buf = '';
while ($num_bytes_to_read) {
my $num_bytes_read = read($fh, $buf, $num_bytes_to_read, length($buf));
if (!$num_bytes_read) {
die "$!\n" if !defined($num_bytes_read);
die "Premature EOF\n";
}
$num_bytes_to_read -= $num_bytes_read;
}
return $buf;
}
sub read_uint32le { unpack('V', read_bytes($_[0], 4)) }
sub read_pstr { read_bytes($_[0], read_uint32le($_[0])) }
my $str = read_pstr($fh);
int read_bytes(FILE* fh, void* buf, size_t num_bytes_to_read) {
while (num_bytes_to_read) {
size_t num_bytes_read = fread(buf, 1, num_bytes_to_read, fh);
if (!num_bytes_read)
return 0;
num_bytes_to_read -= num_bytes_read;
buf += num_bytes_read;
}
return 1;
}
int read_uint32le(FILE* fh, uint32_t* p_i) {
int ok = read_bytes(fh, p_i, sizeof(*p_i));
if (!ok)
return 0;
{ /* Rearrange bytes on non-LE machines */
const char* p = (char*)p_i;
*p_i = ((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0];
}
return 1;
}
char* read_pstr(FILE* fh) {
uint32_t len;
char* buf = NULL;
int ok;
ok = read_uint32le(fh, &len);
if (!ok)
goto ERROR;
buf = malloc(len+1);
if (!buf)
goto ERROR;
ok = read_bytes(fh, buf, len);
if (!ok)
goto ERROR;
buf[len] = '\0';
return buf;
ERROR:
if (p)
free(p);
return NULL;
}
char* str = read_pstr(fh);