免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3341 | 回复: 9
打印 上一主题 下一主题

perl 操作位串和二进制文件 问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-18 13:06 |只看该作者 |倒序浏览
perl中如何把两个数转换成bit后连接起来呢?
如我有两个数, 31 和 37294798, 想把 31 转换成长度为5的bit,然后用27位来储存 37294798, 最后连接成一个32位的vec,有没有好的建议?

另外,如果我的一个str 是由vec生成的很多个这样以32位为单元的二进制串,如何写入到一个binary文件中呢?再如何读出来?因为长度不固定,但是可以一个str写成一行,然后整行读取分析。

最近在研究pack, unpack, vec等函数,但是一直没吃透,希望有懂的可以指点下。

论坛徽章:
0
2 [报告]
发表于 2012-09-18 20:53 |只看该作者
其实,你的需求用sprintf、oct等来做,更容易理解吧,但性能倒是不确认~
我对pack那些模板参数倒是也不熟,翻了下perldoc,纯粹用pack、unpack实现你的需求:

unpack( I, pack( 'b*', unpack( 'b27', pack('i', 37294798 ) ) . unpack( 'b5', pack('c',31) ) ) )

返回的是unsigned,然后你上面说的 5 bits + 27 bits,没说清楚是高、低位,上面的代码把5bits放在了 高位。

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
3 [报告]
发表于 2012-09-19 09:12 |只看该作者
回复 1# picbhan

It seems that can't use vec for your question because the BITS must be 1,2,4,8,16...

$ perldoc -f vec
       vec EXPR,OFFSET,BITS
               Treats the string in EXPR as a bit vector made up of elements
               of width BITS, and returns the value of the element specified
               by OFFSET as an unsigned integer.  BITS therefore specifies the
               number of bits that are reserved for each element in the bit
               vector.  This must be a power of two from 1 to 32 (or 64, if
               your platform supports that).

               If BITS is 8, "elements" coincide with bytes of the input
               string.

               If BITS is 16 or more, bytes of the input string are grouped
               into chunks of size BITS/8, and each group is converted to a
               number as with pack()/unpack() with big-endian formats "n"/"N"
               (and analogously for BITS==64).  See "pack" for details.


   

论坛徽章:
0
4 [报告]
发表于 2012-09-21 10:06 |只看该作者
回复 2# dugu072


    这两天没时间看论坛,没回复,不好意思。

sprintf 加 vec 加 pack / unpack 可以做到, 单纯用vec 也可以。
$c = sprintf("%05b", $a) . sprintf("%027b", $b);
vec($d, 0, 32) = unpack("N", pack("B32", $c));


只用vec需要做位移操作和或操作。
$a = '';
vec($a, 0, 32) = 31;
vec($b, 0, 32) = $d << 5;
$a = $a | $b;

论坛徽章:
0
5 [报告]
发表于 2012-09-21 10:07 |只看该作者
本帖最后由 picbhan 于 2012-09-21 10:08 编辑

回复 3# jason680


    please see #4.

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
6 [报告]
发表于 2012-09-21 11:16 |只看该作者
本帖最后由 jason680 于 2012-09-21 11:21 编辑

回复 5# picbhan

How about this easy way to do it as below:

$value32 =  ($a_5bits << 27 ) + $b_27bits;

or you want it must be 5 and 27 bits only

$value32 =  (($a_5bits & 0x11)<< 27 ) + ($b_27bits & 0x7FFFFFF);


$a_5bits = $value32 >> 27;
$b_27bits = ($value32  & 0x7FFFFFF);  

论坛徽章:
0
7 [报告]
发表于 2012-09-21 15:14 |只看该作者
回复 6# jason680


    Actually, it's not exactly 5 bits and 27 bits.
I use the last 5 bits to store values between 0 and 31, and use first 28 bits to store a very big value (it at most needs 28 bits), hence the last bit of these 28 bits is removed and overlaped by the first bit of the 5 bits, when deparse this 32 bits value, I first deparse last 5 bits to get the small value between 0 and 31, and the add a 0 to the first 27 bits to get the big value, which may 1 less than its orignal value, but it's OK.

Hence I can't sure the easy way you provided will work fine or not.

Like this:
$value32 = (($b_27bits >> 1) << 5) + $a_5bits;

I think this will work fine.

Anyway, thank you!

论坛徽章:
0
8 [报告]
发表于 2012-09-21 15:29 |只看该作者
回复 7# picbhan


    他跟你说英文,你就不必也用英文回他了吧。。

论坛徽章:
0
9 [报告]
发表于 2012-09-21 15:40 |只看该作者
回复 8# sjdy521


    无所谓的,我们大多时候也是用英文写邮件什么的,呵呵

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
10 [报告]
发表于 2012-09-23 15:24 |只看该作者
学习学习,也许以后能用
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP