【问题标题】:Java - Converting ASCII to Binary without leading zerosJava - 将 ASCII 转换为二进制而不带前导零
【发布时间】:2015-08-05 20:38:31
【问题描述】:

我正在使用此代码:

    byte[] bytes = MESSAGE.getBytes();
    StringBuilder str = new StringBuilder();
    for (byte b : bytes) {
        int val = b;
        for (int i = 0; i < 8; i++) {
            str.append((val & 128) == 0 ? 0 : 1);
            val <<= 1;
        }
    }

我正在尝试对其进行修改,以在每个 ASCII 字符的二进制代码附加到二进制 StringBuilder str 之前删除前导零。但问题是前导零的数量是未知的,我只能通过在第一个块之后添加以下内容从整个二进制块中删除它们:

    String MSG = "";
    for(int i = 0; i < str.length(); i++) {
        if(str.charAt(i) == '0')
            MSG = (str.toString()).substring(i+1,str.length());
        else
            break;
    }

有什么想法吗?

【问题讨论】:

  • 你想做什么?
  • 她不想要前导零,因为现在她在使用字符串打印方法时必须删除它们。
  • @brso05 我正在尝试删除每个字符的前导零,然后将它们的二进制文件附加到此处:str.append((val &amp; 128) == 0 ? 0 : 1);

标签: java binary byte ascii


【解决方案1】:

Integer.toBinaryString(yourByte).replaceFirst("0*", "");

一个更完整的例子是。

final StringBuilder builder = new StringBuilder();
String example = "A test string";

for( byte b: example.getBytes()){
    builder.append(Integer.toBinaryString(b).replaceFirst("0*",""));
}   

System.out.println(builder.toString());

【讨论】:

  • 她只想删除前导零,直到找到 1。后面的字节的前导零不会被删除,因为它们的前一个字节有一个前导 1。
  • 我不知道你在说什么。你可以试一试。 ideone.com/AVZc4r
  • "001001" 应转换为 "1100000011000000110001001100000011000000110001",这是该字符串的 ASCII 码的二进制表示(0 是 00110000,1 是 00110001)。您的代码将其转换为“1001”
  • 我的代码只是转换一个字节,我提供了一个字节转换的例子。不将“001001”作为字符串,但表明任何字节字符串都只会删除前导零。例如。我在上面粘贴的代码会将一个字节转换为一串 0 和 1,然后删除前导零。
【解决方案2】:

这个怎么样:

byte[] bytes = MESSAGE.getBytes();
StringBuilder str = new StringBuilder();
for (byte b : bytes) {
    int val = b;
    boolean dontWriteYet = true;
    for (int i = 0; i < 8; i++) {
        int digit = (val & 128) == 0 ? 0 : 1;
        if(digit == 1 && dontWriteYet ) {
            dontWriteYet = false;
        } 
        if (!dontWriteYet) {
            str.append(digit);
        }
        val <<= 1;
    }
    //if all 0's then we must add the 0
    if (dontWriteYet){
        str.append(0);
    }
}

在得到 1 之前基本上不要写入 str。一旦得到 1,然后再写入其余部分。

编辑代码以添加全为 0 的情况。

【讨论】:

  • 啊,是的,看起来我们的想法相同,但执行起来略有不同。
【解决方案3】:

看起来确实很复杂,因为您使用了三元运算符,但实际上修改代码以省略前导零并不难:

byte[] bytes = MESSAGE.getBytes();
StringBuilder str = new StringBuilder();
boolean first = true;
for (byte b : bytes) {
    int val = b;
    for (int i = 0; i < 8; i++) {
        int v = (val & 128) == 0 ? 0 : 1;
        if (v == 1 || !first || i == 7) {
            str.append(v);
            first = false;
        }
        val <<= 1;
    }
}

【讨论】:

  • 智者相通。尽管马特的解决方案非常巧妙。
【解决方案4】:

最简单的解决方案是在找到 1 时使用标志进行标记,并且仅在该标志为真时添加字符。该解决方案有一个不便之处,您必须每次检查该标志。一个更有效的解决方案是使用不同的代码来遍历零和添加字符:

static class Indexes {

    int indexByte;
    int indexBit;
}

static void traverseZeroes(byte[] bytes, Indexes indexes) {
    for (indexes.indexByte = 0; indexes.indexByte < bytes.length; ++indexes.indexByte) {
        int val = bytes[indexes.indexByte];
        for (indexes.indexBit = 0; indexes.indexBit < 8; ++indexes.indexBit) {
            if ((val & 128) != 0) {
                return;
            }
            val <<= 1;
        }
    }
}

static void addBits(byte[] bytes, Indexes indexes, StringBuilder str) {
    if ( indexes.indexByte>=bytes.length ) {
        str.append('0');
        return;
    }
    int val = bytes[indexes.indexByte] << indexes.indexBit;
    for (;;) {
        while (indexes.indexBit < 8) {
            str.append((val & 128) == 0 ? 0 : 1);
            val <<= 1;
            ++indexes.indexBit;
        }
        indexes.indexBit = 0;
        ++indexes.indexByte;
        if (indexes.indexByte >= bytes.length) {
            break;
        }
        val = bytes[indexes.indexByte];
    }
}

public static void main(String[] args) {
    byte[] bytes = MESSAGE.getBytes();
    StringBuilder str = new StringBuilder();
    Indexes indexes = new Indexes();
    traverseZeroes(bytes, indexes);
    addBits(bytes, indexes, str);
    System.out.println(str);
}

在不太可能的情况下,性能足够重要,请使用它。否则使用标志。

【讨论】:

  • 你只需要检查 0 上的标志,所以在你找到第一个 1 之前,这个想法大致相同,然后它会变得更好。另外我认为最好使用 0 或 '0' 这样就不会创建任何对象。否则我同意。
  • 没错,我已经把“0”改成了“0”。
【解决方案5】:

您能不能以Integer 开头的ASCII 码,然后调用.toBinaryString()?我认为这将摆脱零。 Docs are here if it helps.

要获得Integer 值,您可以直接从角色中投射。

public String characterToBinary(char c){
    int ascii = (int) c;
    return Integer.toBinaryString(ascii);
}

如果是Integer,您还可以访问其他有用的方法,例如.numberOfLeadingZeros()。

【讨论】:

    猜你喜欢
    • 2016-10-02
    • 2015-11-18
    • 2013-05-31
    • 2014-07-17
    • 2014-08-16
    • 2013-04-01
    • 1970-01-01
    • 2014-08-03
    相关资源
    最近更新 更多