【问题标题】:encoding and decoding utf8 string and its bytes in Java在 Java 中编码和解码 utf8 字符串及其字节
【发布时间】:2014-05-06 14:05:12
【问题描述】:

我正在做一个项目,我需要在 java 中对字符串进行编码和编码。我的字符串是由波斯字符组成的 UTF-8 字符串。我只是想用一个静态字符对每个字节进行异或,然后用相同的静态字符再次对它进行异或。

我写了下面的代码,但它完全错了!我用英文字符检查它,它可以工作。

我该如何解决这个问题?

String str = "س";
char key = 'N';
byte bKey = (byte) key;

byte[] b = str.getBytes();

for (int i = 0; i < b.length; i++)
{
    b[i] = Byte.valueOf((byte) (b[i] ^ bKey));
}

String str1 = new String(b);
b = str1.getBytes();

for (int i = 0; i < b.length; i++)
{
    b[i] = (byte) (b[i] ^ bKey);
}

String str2 = new String(b);

【问题讨论】:

    标签: java string utf-8


    【解决方案1】:

    当您从变异字节创建 str1 时,问题就来了。假设您的默认编码是 UTF8,当您说 String str1 = new String(b); 时,您是在说这里是 UTF8 编码中的一些字节,请为我构建一个不错的字符串。但是因为你对字节进行了异或,编码是无效的 UTF8,Java 不太知道如何处理它。如果您查看使用 b = str1.getBytes(); 从 str1 检索的字节,您会发现它们与您创建字符串时使用的字节不同!

    您真的不应该从“废话”字节创建字符串 --- 您真的需要将异或字节存储回字符串中吗?

    如果你真的想这样做,你可以通过使用单字节编码来欺骗系统,其中所有可能的字节值都是有效的。然后您可以确定您放入字符串的字节与您取出的字节相同。这是一个对我有用的示例:

    public class B {
        static public void main(String[] args) throws Exception {
            String str = "س";
            System.out.println(str);
            char key = 'N';
            byte bKey = (byte) key;
    
            byte[] b = str.getBytes("UTF8");
    
            System.out.println("Original bytes from str:");
            for (int i = 0; i < b.length; i++) {
                System.out.println(b[i]);
            }
    
            System.out.println("Bytes used to create str1:");
            for (int i = 0; i < b.length; i++) {
                b[i] = Byte.valueOf((byte) (b[i] ^ bKey));
                System.out.println(b[i]);
            }
    
            String str1 = new String(b, "Cp1256");
    
            b = str1.getBytes("Cp1256");
    
            System.out.println("Bytes retrieved from str1:");
            for (int i = 0; i < b.length; i++) {
                System.out.println(b[i]);
                b[i] = (byte) (b[i] ^ bKey);
            }
    
            System.out.println("Bytes used to create str2:");
            for (int i = 0; i < b.length; i++) {
                System.out.println(b[i]);
            }
    
            String str2 = new String(b, "UTF8");
            System.out.println(str2);
        }
    }
    

    我得到的输出是:

    س
    Original bytes from str:
    -61
    -65
    -30
    -119
    -91
    Bytes used to create str1:
    -115
    -15
    -84
    -57
    -21
    Bytes retrieved from str1:
    -115
    -15
    -84
    -57
    -21
    Bytes used to create str2:
    -61
    -65
    -30
    -119
    -91
    س
    

    【讨论】:

    • 谢谢!它完美地工作。实际上我使用 XOR 来简单地加密一些数据。我想将异或数据存储在我的数据库中并在我的程序中解密!但这是一个问题,我用我的密钥对字符进行异或运算,它无需使用任何编码即可工作。为什么?我的意思是 char c = str.charAt(i) ^ 键并将它们收集到字符串中。为什么它有效?再次感谢您的解释:))
    • 老实说,我必须更准确地了解您在做什么并玩弄一下才能真正理解它,但基本上有两种可能性:在您 xor 之后可能很幸运剩下的字符仍然是有效的 UTF-16 值(Java 内部用于字符的内存编码)。或者在这种情况下,Java 可能不会验证该值,因为它只需要在需要转换为特定编码或从特定编码转换时“理解”该字符。在任何一种情况下,您都会从字符串中完全取出您输入的内容,这是这里的真正要求。
    【解决方案2】:

    当您尝试使用 XORed 字节创建新的 String 时会出现问题:

    String str1 = new String(b);
    b = str1.getBytes();
    

    由于异或字节不能形成有效的 Unicode/UTF-8 字符,因此 String 无效,getBytes() 不会返回您认为的结果。

    如果您跳过翻译回String,您的代码将正常工作。

    【讨论】:

      【解决方案3】:

      首先,str.getBytes();表示使用默认字符集将字符转换为字节。并且字符串 str1 = new String(b);也在使用默认字符集。这里没有与 UTF-8 相关的内容。

      而且在Java中做位操作有点棘手,尝试将所有b[i]改为(b[i] & 0xff)。

      【讨论】:

      • 嗯!我在标题中添加了 utf8,因为这个问题只是 utf8 编码。正如我所说,它适用于英文字符。你的答案没有用:((我改变了 b[i] & 0xff 但结果是一样的
      猜你喜欢
      • 1970-01-01
      • 2016-05-31
      • 2012-03-25
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多