简体   繁体   English

使用ZXing对byte []进行编码和解码

[英]Encoding and decoding byte[] with ZXing

I am developping an Android app, and I need to encode and decode a bytes array in a QRCode generated with the ZXing app. 我正在开发一个Android应用程序,我需要对使用ZXing应用程序生成的QRCode中的字节数组进行编码和解码。 My problem is that my message decoded does not exactly match the generated byte array. 我的问题是我的消息解码与生成的字节数组不完全匹配。 I tried to create a QRCode based on a byte array containing incrementing indexes, ie 我尝试基于包含递增索引的字节数组创建QRCode,即

input = [0, 1, 2, ..., 124, 125, 126, 127, -128, -127,... -3, -2, -1, 0, 1, 2, ...]

And after encoding the message in the QRCode and decoding it on the responder side, I obtain the following byte array output: 在对QRCode中的消息进行编码并在响应方侧对其进行解码后,我获得了以下字节数组输出:

output = [0, 1, 2, ..., 124, 125, 126, 127, 63, 63,... 63, 63, 63, 0, 1, 2, ...]

All the "negative" byte values are turned to ASCII char 63: '?' 所有“负”字节值都转为ASCII字符63:'?' question mark characters. 问号字符。 I assume that something is going wrong with the encoding charset, but since I am using ISO-8859-1 which everyone claims to be the solution of such kind of issue ( other topic treating the same kind of issue or here ), I don't see where is my mistake, or if I am skipping a step during the instanciation of the encoding or the decoding. 我假设编码字符集出了问题,但由于我使用的是ISO-8859-1,每个人都声称是这类问题的解决方案( 其他主题处理相同类型的问题在这里 ),我不知道看看我的错误在哪里,或者我是否在编码或解码过程中跳过了一步。 Here is the code that I execute to encode a given byte array: 这是我执行以编码给定字节数组的代码:

String text = "";
byte[] res = new byte[272];
for (int i = 0; i < res.length; i++) {
    res[i] = (byte) (i%256);
}
try {
    text = new String(res, "ISO8859_1");
} catch (UnsupportedEncodingException e) {
    // TODO
}
Intent intent = new Intent(Intents.Encode.ACTION);
Intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT);
intent.putExtra(Intents.Encode.FORMAT, "ISO8859_1");
intent.putExtra(Intents.Encode.DATA, text);
intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString());

boolean useVCard = intent.getBooleanExtra(USE_VCARD_KEY, false);
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(activity, intent, dimension, useVCard);
Bitmap bitmap = qrCodeEncoder.encodeAsBitmap();

And to decode a QRCode, I send the following Intent 为了解码QRCode,我发送以下Intent

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.qrcodeDecoding);

    Intent intent = new Intent(Intents.Scan.ACTION);
    intent.putExtra(Intents.Scan.MODE, Intents.Scan.QR_CODE_MODE);
    startActivityForResult(intent, 0);
}

And wait for Result: 并等待结果:

@Override
protected void onActivityResult(int request, int result, Intent data)
{
    if(request == 0)
    {
        //action
        if(result == RESULT_OK)
        {
            String res = data.getStringExtra(Intents.Scan.RESULT);
            byte[] dat = null;

            try{
                    dat = res.getBytes("ISO8859_1");
            } catch(UnsopportedEncodingException e) {
                    //TODO
            }
        }
        else if(result == RESULT_CANCELED)
        {
            //TODO
        }
    }

}

Could you please tell me where are my mistakes, or where should I look at? 你能告诉我我的错误在哪里,或者我应该在哪里看?

Thank you a lot, 非常感谢,

Franck 弗兰克

In one of my apps I needed to encode and decode a bytes array in a QRCode generated with the ZXing app. 在我的一个应用程序中,我需要对使用ZXing应用程序生成的QRCode中的字节数组进行编码和解码。 As the byte array contained compressed text data I wanted to avoid base64 encoding. 由于字节数组包含压缩文本数据,我想避免使用base64编码。 It is possible to do this but as I have so far not seen a complete set of code snippets I will post them here. 可以这样做但是因为到目前为止我还没有看到一整套代码片段,所以我会在这里发布它们。

Encoding: 编码方式:

public void showQRCode(Activity activity, byte[] data){
  Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
  intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
  intent.putExtra("ENCODE_SHOW_CONTENTS", false);
  intent.putExtra("ENCODE_DATA", new String(data, "ISO-8859-1"));
  activity.startActivity(intent);
}

Start scanning: 开始扫描:

public static void startQRCodeScan(Activity activity){
  Intent intent = new Intent(com.google.zxing.client.android.SCAN);
  intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
  intent.putExtra("CHARACTER_SET", "ISO-8859-1");
  activity.startActivityForResult(intent, 0);
}

Scan result handler: 扫描结果处理程序

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
  byte[] result = intent.getStringExtra("SCAN_RESULT").getBytes("ISO-8859-1");
  ...
}

I think not setting CHARACTER_SET to ISO-8859-1 in the intent data for starting the scan is the point that made the code of the original question fail. 我认为在开始扫描的意图数据中没有将CHARACTER_SET设置为ISO-8859-1是使原始问题的代码失败的点。 It took me quite some time to dig this out as I have not seen this clearly posted anywhere and Latin 1 encoding is the standard encoding for QR code in Xzing. 我花了很长时间才把它挖出来,因为我没有看到这个明显张贴在任何地方,拉丁文1编码是Xzing中QR码的标准编码。 Especially tricky is the fact that the Xzing online decoder http://zxing.org/w/decode.jspx does not set CHARACTER_SET as well so that the generated QR code looks faulty when decoded on this site. 特别棘手的是,Xzing在线解码器http://zxing.org/w/decode.jspx也没有设置CHARACTER_SET,因此生成的QR码在此站点上解码时看起来有问题。

You are making the mistake of thinking that you can turn arbitrary binary data into a valid string without using some kind of armouring. 您错误地认为可以将任意二进制数据转换为有效字符串而不使用某种铠装。 It doesn't work. 它不起作用。 Binary -> text -> binary is lossy using any of the standard character sets / encoding. Binary - > text - > binary使用任何标准字符集/编码都是有损的。 (Hint: using UTF-8 won't work either.) (提示:使用UTF-8也不起作用。)

You should use something like base64 encoding or hexadecimal encoding to ensure that the binary data doesn't get mangled. 您应该使用类似base64编码或十六进制编码的方法来确保二进制数据不会被破坏。

Conceptually, QR codes encode text, not bytes. 从概念上讲,QR码编码文本而不是字节。 Inside of course they translate input to a series of bytes, though that's opaque to the caller. 当然,他们将输入转换为一系列字节,尽管这对调用者来说是不透明的。 You are right that, as it happens, choosing the right encoding would let you sneak the bytes through, and ISO-8859-1 is the right choice here. 你是对的,正如它发生的那样,选择正确的编码会让你偷偷摸摸通过,而ISO-8859-1是正确的选择。 It does work, actually. 实际上它确实有效。

ASCII is not possible since it does not define chars for >= 128, and UTF-8 is definitely not going to work ASCII是不可能的,因为它没有定义> = 128的字符,而UTF-8肯定不会起作用

The issue here is probably your code. 这里的问题可能是你的代码。 I am not sure what you're attempting here... it looks like you're setting up to send an Intent somewhere (to Barcode Scanner?) but then you don't, you're just making an Intent and sending it to some code you copied from the project? 我不确定你在这里尝试了什么......看起来你正准备在某个地方发送一个Intent (到Barcode Scanner?)但是你没有,你只是制作一个Intent并发送给它你从项目中复制了一些代码? I imagine something's gone wrong with how you are setting extras to the Intent . 我想象你如何为Intent设置额外内容出了问题。

This should be much simpler if you're doing it within your app. 如果你在你的应用程序中这样做,这应该会简单得多。 Just reuse QRCodeEncoder.encodeAsBitmap() directly and delete the rest of this. 只需直接重用QRCodeEncoder.encodeAsBitmap()并删除其余部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM