java 使用 ZXing 对 byte[] 进行编码和解码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11067723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Encoding and decoding byte[] with ZXing
提问by franckysnow
I am developping an Android app, and I need to encode and decode a bytes array in a QRCode generated with the ZXing app. 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, i.e.
我正在开发一个 Android 应用程序,我需要对 ZXing 应用程序生成的 QRCode 中的字节数组进行编码和解码。我的问题是我解码的消息与生成的字节数组不完全匹配。我试图基于包含递增索引的字节数组创建一个 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: '?' 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 issueor 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. Here is the code that I execute to encode a given byte array:
所有“负”字节值都转换为 ASCII 字符 63:'?' 问号字符。我认为编码字符集有问题,但由于我使用的是 ISO-8859-1,每个人都声称它是此类问题的解决方案(其他主题处理同类问题或此处),我不t 看看我的错误在哪里,或者我是否在编码或解码的实例化过程中跳过了一个步骤。这是我执行以对给定字节数组进行编码的代码:
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
弗兰克
采纳答案by Stephen C
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. (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 编码或十六进制编码的方法来确保二进制数据不会被破坏。
回答by Nantoka
In one of my apps I needed to encode and decode a bytes array in a QRCode generated with the ZXing app. As the byte array contained compressed text data I wanted to avoid base64 encoding. 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.
在我的一个应用程序中,我需要对 ZXing 应用程序生成的 QRCode 中的字节数组进行编码和解码。由于字节数组包含压缩文本数据,我想避免使用 base64 编码。这样做是可能的,但由于到目前为止我还没有看到一组完整的代码片段,我将它们张贴在这里。
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. 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. Especially tricky is the fact that the Xzing online decoder http://zxing.org/w/decode.jspxdoes not set CHARACTER_SET as well so that the generated QR code looks faulty when decoded on this site.
我认为在开始扫描的意图数据中未将 CHARACTER_SET 设置为 ISO-8859-1 是导致原始问题代码失败的原因。我花了很长时间才把它挖掘出来,因为我还没有在任何地方看到清楚地张贴这个,拉丁 1 编码是 Xzing 中二维码的标准编码。尤其棘手的是,Xzing 在线解码器http://zxing.org/w/decode.jspx也没有设置 CHARACTER_SET,因此生成的二维码在本网站上解码时看起来有问题。
回答by Sean Owen
Conceptually, QR codes encode text, not bytes. 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. It does work, actually.
从概念上讲,二维码编码文本,而不是字节。当然,他们将输入转换为一系列字节,尽管这对调用者来说是不透明的。你是对的,碰巧,选择正确的编码会让你偷偷通过字节,而 ISO-8859-1 是这里的正确选择。它确实有效。
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? I imagine something's gone wrong with how you are setting extras to the Intent
.
这里的问题可能是您的代码。我不确定你在这里尝试什么......看起来你正在设置发送某个Intent
地方(到条形码扫描仪?)但是你没有,你只是制作一个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()
直接重用并删除其余部分即可。