【问题标题】:Converting a String representation of bits to a byte将位的字符串表示形式转换为字节
【发布时间】:2012-01-06 17:02:05
【问题描述】:

我刚刚开始学习文件压缩,但遇到了一些障碍。我有一个应用程序,它将诸如“程序”之类的字符串编码为压缩二进制表示"010100111111011000"(请注意,这仍然存储为字符串)。

Encoding
g       111
r       10
a       110
p       010
o       011
m       00

现在我需要使用FileOutputStream 将其写入文件系统,我遇到的问题是,如何将字符串“010100111111011000”转换为要写入的byte[]/bytes FileOutputStream的文件系统?

我以前从未使用过比特/字节,所以我在这里有点走投无路。

【问题讨论】:

  • 您谈论“压缩二进制表示”,然后说您有一个 18 个字符长(“010100111111011000”)的 String 来表示一个 7 个字符长的单词(“程序”)。你确定你的意思是你在问什么?通常,您会将这些位设置为 X 个字节(在本例中为 3 个)。
  • 查找“位移运算符”:>>>>><<
  • Brian,原始消息翻译成二进制后大小为56bits,编码后的消息只有18bits。凯文,人们一直在告诉我,但我仍然无法在使用这些运算符和能够将其转换为字节数组之间建立联系。
  • @JohnLotacs - 不,不是,如果你说的是Strings,你说你的问题是混乱的根源。如果你有一个String 如你所说,你没有位。您有一堆字符 01 (具体来说,每个字符都有一个 16 位 Unicode 字符,使您的内存在 String 对象的开销之前使用 36 个字节) - 要清楚,如果你有String 你有一组位的文本表示,用字符 0 和 1 表示。
  • Brian,这就是问题所在,将位的字符串表示形式转换为一组字节。

标签: java byte bit-manipulation bits huffman-code


【解决方案1】:

移位运算符简介:

首先,我们有左移运算符x << n。这会将x 中的所有位左移n 位,用零填充新位:

      1111 1111 
<< 3: 1111 1000

接下来,我们有带符号的右移运算符x &gt;&gt; n。这会将x 中的所有位右移 n,将符号位复制到新位中:

      1111 1111 
>> 3: 1111 1111

      1000 0000
>> 3: 1111 0000

      0111 1111 
>> 3: 0000 1111

最后,我们有了零填充右移运算符x &gt;&gt;&gt; n。这会将x 中的所有位右移n 位,用零填充新位:

       1111 1111 
>>> 3: 0001 1111

您可能还会发现位或运算符x | y 很有用。这将比较xy 中每个位置的位,如果在xy 中打开,则设置新数字的位,否则关闭:

  1010 0101
| 1010 1010
  ---------
  1010 1111

对于手头的问题,您应该只需要前面的运算符,但为了完整起见,这里是最后两个:

位与运算符 x &amp; y 将输出中的位设置为 1 当且仅当该位在 xy 中都打开:

  1010 0101
& 1010 1010
  ---------
  1010 0000

按位异或运算符x ^ y 将输出位设置为一个,如果该位在一个数字或另一个数字中打开,但不是两者都打开:

  1010 0101
^ 1010 1010
  ---------
  0000 1111

现在,将这些应用到手头的情况:

您将需要使用位移运算符来添加和操作位。根据它们的字符串表示开始在右侧设置位并将它们移动。继续直到你到达一个字节的结尾,然后移动到下一个字节。假设我们要创建“1100 1010”的字节表示:

Our byte    Target
---------   --------
0000 0000
            1100 1010
0000 0001   ^
            1100 1010
0000 0011    ^
            1100 1010
0000 0110     ^
            1100 1010
0000 1100      ^
            1100 1010
0001 1001        ^
            1100 1010
0011 0010         ^
            1100 1010
0110 0101          ^
            1100 1010
1100 1010           ^

当然,我会留给你把它应用到你的工作中。

【讨论】:

  • 一个问题,把我的字节从0000 0001开始,这和写字节b = 1是一样的; ?我不确定,由于字节的带符号性质,如何知道二进制表示是什么,因为我不知道什么位代表符号。
  • 您可以这样做,但为了保持一致性,您需要从零字节开始,然后输入 forwhile 循环。我会稍微修改一下这个例子,看看我能不能让它更清楚一点。
【解决方案2】:

将您的String 切成8 的长度并致电Byte#parseByte。如果将radix 设置为2,它会将String 解析为二进制数。

【讨论】:

  • 线程“主”java.lang.NumberFormatException 中的异常:值超出范围。 Value:"10000000" Radix:2 它只适用于长度为 7 的情况,除非有前导零,知道吗?
  • @John Lotacs 我不知道为什么会这样,但您可以使用Integer#parseInt 并将其转换为byte 以获得解决方法。
  • @jeff 这样做是因为byte 已签名,所以它需要是-111 1111+111 1111(-128 到+127)。具有1000 0000 位的字节实际上是-128,并且必须作为-1000 0000 提供给解析器。
  • @Kevin 为什么不能只接受1000 000?只是编码人员有点懒惰还是我错过了什么?
  • parseByte 方法解析文本的值,而不是单个位。 1000 0000 是 128,这超出了 byte 的范围,最大为 127。它在 unsigned byte 的范围内,但 Java 没有无符号类型(除了,我相信,@ 987654340@).
【解决方案3】:

我猜,您想将这些零和一作为二进制值写入文件。我是这样的,您可以每次都迭代带有 8 个符号的字符串(String.substring() 或 smth),并使用 Byte(String) 构造函数创建字节。 这是我目前想到的最简单的解决方案。

如果我对这个问题的看法不正确,请详细说明。

【讨论】:

  • 我试过了,Byte(String) 构造函数将接受一个字符串“0011”并将其解释为十进制数 11。
  • 这就是为什么你应该使用 Byte(String s, int radix) 构造函数来设置二进制基数。
猜你喜欢
  • 1970-01-01
  • 2020-07-21
  • 2011-03-27
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
相关资源
最近更新 更多