不使用编码将字符串转换为/从字节数组转换

4
我有一个通过网络连接读取的字节数组,我需要将其转换为字符串而不使用任何编码,即仅通过将每个字节视为字符的低位并将高位保留为零。 我还需要做相反的操作,其中我知道字符的高位将始终为零。
在网上搜索可以得到几个类似的问题,所有这些问题的回答都表明原始数据源必须更改。 这不是一个选项,请不要建议它。
在C语言中这很简单,但Java似乎要求我编写自己的转换程序,这可能非常低效。 我是否错过了一种简便的方法?

new String(yourByteArray);? - tkausl
你是如何确定它可能非常低效的? - Kayaman
2
为什么要转换为字符串?如果你有一个byte[] ,那么你可以按原样保留它吗?如果你不知道编码,那么你怎么可能希望将这些字节解释为字符串? - Ben Thurley
5个回答

5
不,你没有错过任何东西。这是因为 Stringchar 都是用于文本的。如果你不想将数据处理成文本,这完全合理。你可以采用你提出的困难方法来处理。
另一种选择是假设一种允许任意字节值序列(0-255)的字符编码。ISO-8859-1 或 IBM437 都符合条件。(Windows-1252 仅有 251 个代码点。UTF-8 不允许任意序列。)如果使用 ISO-8859-1,则生成的字符串与你采用的困难方法相同。
至于效率,处理字节数组最有效的方法是保持它作为字节数组。

我认为这是一个不错的解决方案。String s = new String(in, "ISO-8859-1"); 对我有用,但会切掉尾随的零,所以我认为它并不完全等同于更困难的方法。 - cagney

2
这将把一个字节数组转换成一个字符串,只填充其高8位。
public static String stringFromBytes(byte byteData[]) {
    char charData[] = new char[byteData.length];
    for(int i = 0; i < charData.length; i++) {
        charData[i] = (char) (((int) byteData[i]) & 0xFF);
    }
    return new String(charData);
}

效率应该相当不错。就像本·瑟雷所说,如果性能确实是问题,首先不要将其转换为字符串,而是直接使用字节数组进行操作。


0

0

这里是一个示例代码,它可以将 String 转换为 byte array,然后再转回 String,而不需要进行编码。

public class Test
{

    public static void main(String[] args)
    {
        Test t = new Test();
        t.Test();
    }

    public void Test()
    {
        String input = "Hèllo world";
        byte[] inputBytes = GetBytes(input);
        String output = GetString(inputBytes);
        System.out.println(output);
    }

    public byte[] GetBytes(String str)
    {
        char[] chars = str.toCharArray();
        byte[] bytes = new byte[chars.length * 2];
        for (int i = 0; i < chars.length; i++)
        {
            bytes[i * 2] = (byte) (chars[i] >> 8);
            bytes[i * 2 + 1] = (byte) chars[i];
        }

        return bytes;
    }

    public String GetString(byte[] bytes)
    {
        char[] chars = new char[bytes.length / 2];
        char[] chars2 = new char[bytes.length / 2];
        for (int i = 0; i < chars2.length; i++)
            chars2[i] = (char) ((bytes[i * 2] << 8) + (bytes[i * 2 + 1] & 0xFF));

        return new String(chars2);

    }
}

谢谢您的建议。我已经实施了类似的东西,现在一切似乎都很顺利。 - M Phillips
而Java的String类有String.getBytes()和new String(byte[])来实现这一点。 - tkausl
3
使用的编码是UTF-16。可能会创建无效的UTF-16代码单元序列,因此任何您将字符串传递给的函数都有权抛出异常,正如Unicode规范所建议的那样。 - Tom Blodget
@tkausl,方法getBytes现在已经过时。 - D.A.H

-1

字符串已经编码为Unicode/UTF-16。UTF-16意味着它可以使用最多2个字符串“字符”(char)来表示一个可显示的字符。你真正想要使用的是:

byte[] bytes = System.Text.Encoding.Unicode.GetBytes(myString); 

将字符串转换为字节数组。这与您上面所做的完全相同,只是性能快了10倍。如果您想将传输数据减少近一半,我建议将其转换为UTF8(ASCII是UTF8的子集) - 这是互联网90%时间使用的格式,通过调用:

byte[] bytes = Encoding.UTF8.GetBytes(myString);

要将其转换回字符串,请使用:

String myString = Encoding.Unicode.GetString(bytes); 

或者

String myString = Encoding.UTF8.GetString(bytes);

请注意标签。这段代码是针对C#/.NET的,但问题被标记为[java]。相同的逻辑适用,并且库类似。欢迎来到Stack Overflow。 - Tom Blodget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接