解码Z64(ZB64)字符串 [英] Decoding Z64 (ZB64) string

查看:892
本文介绍了解码Z64(ZB64)字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力分解NiceLabel标签制作软件生成的ZPL标签定义。在大多数情况下,我不必担心对Z64进行解码,因为它只是经过编码的图形,并且不需要更改基础数据。



但是我



无论如何,Z64或ZB64字符串是通过压缩创建的,由于某种原因,该行可能被标签用作图形。

原始数据使用LZ77并将其编码为Base64,然后在末尾附加CRC。



完整测试字符串示例:



'pre> :Z64:eJztkDFOxDAQRb81hRsULmBtruECyRwpZYpFGLmg5AhwFKMUuYal9CtL26QwHsbe3RMguv3lz9P85wD3 / CWaiZ + 56OjqWA44cwKIAyfeXXL1sQ7YWqd54czltTge + VOdOQsXFp8TrLUw9KEW3 + 6pLU4Zk3mC0ataonSEzU8JMywGCiFcue + c8YLGvYcLF5a + 68WFhbvtRs5jdmVkWolj96vgXe / it7eucT + 0 + gxV5N5RrdTveQpevhnxO + BEfRe0xIzc / EbUzkn3lhLSIH6DdFeu + c39Hb7c7vksfrJryB8vu6A4cxE / NjpK1 / 6LkJZ3 + nL1gaLt3D33 / ED + AehfkrY =:6C38

测试字符串目标示例:

  eJztkDFOxDAQRb81hRsULmBtruEC yRwpZYpFGLmg5AhwFKMUuYal9CtL26QwHsbe3RMguv3lz9P85wD3 / CWaiZ + 56OjqWA44cwKIAyfeXXL1sQ7YWqd54czltTge + VOdOQsXFp8TrLUw9KEW3 + 6pLU4Zk3mC0ataonSEzU8JMywGCiFcue + c8YLGvYcLF5a + 68WFhbvtRs5jdmVkWolj96vgXe / it7eucT + 0 + gxV5N5RrdTveQpevhnxO + BEfRe0xIzc / EbUzkn3lhLSIH6DdFeu + c39Hb7c7vksfrJryB8vu6A4cxE / NjpK1 / 6LkJZ3 + nL1gaLt3D33 / ED + AehfkrY = 

我的代码进行解码/解压缩:

 静态字符串DecompressZb64(字符串压缩字符串)
{
var b64 = SmartWarehouse.Shared.Utils.Parser.ConvertFromBase64(compressedString);
var encoding = new ASCIIEncoding();
var inBytes = Encoding.ASCII.GetBytes(b64);
var outBytes =新字节[inBytes.Length];
尝试
{
使用(var memoryStream = new MemoryStream())
使用(var decompressionStream = new DeflateStream(memoryStream,CompressionMode.Decompress))
{
decompressionStream.Read(outBytes,0,inBytes.Length);
}

返回encoding.GetString(outBytes);
}
catch(异常e)
{
// TODO:文档异常
Console.WriteLine(e.Message);
}

返回字符串。
}

当前例外:

 块长度与其补码不匹配。 

Stacktrace:

 < System.IO.Compression.Inflater.DecodeUncompressedBlock(Boolean& end_of_block)
在System.IO.Compression.Inflater.Decode()
在System.IO.Compression.Inflater.Inflate (Byte []字节,Int32偏移量,Int32长度)
,位于System.IO.Compression.DeflateStream.Read(Byte []数组,Int32偏移量,Int32计数)
,位于SmartWarehouse.Tools.Program.DecompressZb64 (字符串压缩字符串)在C:\Users\ [user_dir] \Source\Repos\Handheld中。[user]。[fork] \SmartWarehouse.Tools\Program.cs:line 511

更新:



我正在调查这个,发现了 SO发布基本上是同样的问题。因此,我做了一些进一步的研究,发现这篇文章来自2007年的博客。其中讨论了一种变通方法,因为这些字节实际上未包含在RFC规范中,所以跳过了输入数组中的前2个字节。



代码更改:

 静态字符串DecompressZb64(string compressionString)
{
var b64 = Convert.FromBase64String(compressedString);
var encoding = new ASCIIEncoding();
var outBytes =新字节[b64.Length-2];
试试
{
使用(var memoryStream = new MemoryStream(b64))
{
memoryStream.ReadByte();
memoryStream.ReadByte();
使用(var decompressionStream = new DeflateStream(memoryStream,CompressionMode.Decompress))
{
decompressionStream.Read(outBytes,0,b64.Length-2);
}
}

返回encoding.GetString(outBytes);
}
catch(异常e)
{
// TODO:文档异常
Console.WriteLine(e.Message);
}

返回字符串。
}

此代码更改实际上不再产生异常,但是不会正确解压缩并返回以下结果:

  \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 


解决方案

该数据对我来说不错,我从中得到了这张图片:





这是一个单色位图,每个像素一位。



您的代码直到最后才读流中实际上有1280字节的图像数据,然后可以将其解码为上面的图像。


I'm working on breaking down ZPL label definitions generated by NiceLabel label making software. For the most part I don't have to worry about decoding the Z64 because it is just encoded graphics and I don't need to change the underlying data.

However I have a line of text that is used as a graphic by the label for some reason probably due to Font's or something.

Anyways, the Z64 or ZB64 string is created by compressing the original data using LZ77 and encoding that as Base64 and then appending a CRC at the end.

TEST STRING FULL EXAMPLE:

:Z64:eJztkDFOxDAQRb81hRsULmBtruECyRwpZYpFGLmg5AhwFKMUuYal9CtL26QwHsbe3RMguv3lz9P85wD3/CWaiZ+56OjqWA44cwKIAyfeXXL1sQ7YWqd54czltTge+VOdOQsXFp8TrLUw9KEW3+6pLU4Zk3mC0ataonSEzU8JMywGCiFcue+c8YLGvYcLF5a+68WFhbvtRs5jdmVkWolj96vgXe/it7eucT+0+gxV5N5RrdTveQpevhnxO+BEfRe0xIzc/EbUzkn3lhLSIH6DdFeu+c39Hb7c7vksfrJryB8vu6A4cxE/NjpK1/6LkJZ3+nL1gaLt3D33/Ed+AehfkrY=:6C38

TEST STRING TARGET EXAMPLE:

eJztkDFOxDAQRb81hRsULmBtruECyRwpZYpFGLmg5AhwFKMUuYal9CtL26QwHsbe3RMguv3lz9P85wD3/CWaiZ+56OjqWA44cwKIAyfeXXL1sQ7YWqd54czltTge+VOdOQsXFp8TrLUw9KEW3+6pLU4Zk3mC0ataonSEzU8JMywGCiFcue+c8YLGvYcLF5a+68WFhbvtRs5jdmVkWolj96vgXe/it7eucT+0+gxV5N5RrdTveQpevhnxO+BEfRe0xIzc/EbUzkn3lhLSIH6DdFeu+c39Hb7c7vksfrJryB8vu6A4cxE/NjpK1/6LkJZ3+nL1gaLt3D33/Ed+AehfkrY=

My Code to Decode / Decompress:

static string DecompressZb64(string compressedString)
{
    var b64 = SmartWarehouse.Shared.Utils.Parser.ConvertFromBase64(compressedString);
    var encoding = new ASCIIEncoding();
    var inBytes = Encoding.ASCII.GetBytes(b64);
    var outBytes = new byte[inBytes.Length];
    try
    {
        using (var memoryStream = new MemoryStream())
        using (var decompressionStream = new DeflateStream(memoryStream, CompressionMode.Decompress))
        {
            decompressionStream.Read(outBytes, 0, inBytes.Length);
        }

        return encoding.GetString(outBytes);
    }
    catch (Exception e)
    {
        // TODO: DOcument exception
        Console.WriteLine(e.Message);
    }

    return string.Empty;
}

Current Exception:

Block length does not match with its complement.

Stacktrace:

   at System.IO.Compression.Inflater.DecodeUncompressedBlock(Boolean& end_of_block)
   at System.IO.Compression.Inflater.Decode()
   at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
   at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
   at SmartWarehouse.Tools.Program.DecompressZb64(String compressedString) in C:\Users\[user_dir]\Source\Repos\Handheld.[user].[fork]\SmartWarehouse.Tools\Program.cs:line 511

UPDATE:

I was looking into this and I found this SO post it is essentially the same issue. So i did some more research and i found this article on a blog from 2007. Which discusses a workaround by skipping the first 2 bytes in the input array due to those bytes not actually being included in the RFC specification.

CODE CHANGE:

static string DecompressZb64(string compressedString)
{
    var b64 = Convert.FromBase64String(compressedString);
    var encoding = new ASCIIEncoding();
    var outBytes = new byte[b64.Length - 2];
    try
    {
        using (var memoryStream = new MemoryStream(b64))
        {
            memoryStream.ReadByte();
            memoryStream.ReadByte();
            using (var decompressionStream = new DeflateStream(memoryStream, CompressionMode.Decompress))
            {
                decompressionStream.Read(outBytes, 0, b64.Length - 2);
            }
        }

        return encoding.GetString(outBytes);
    }
    catch (Exception e)
    {
        // TODO: DOcument exception
        Console.WriteLine(e.Message);
    }

    return string.Empty;
}

This code change doesn't actually produce an exception anymore however it doesn't decompress properly and returns this result:

"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

解决方案

That data looks fine to me, I got this image out of it:

It's a monochrome bitmap, one bit per pixel.

Your code didn't read until the end of the stream, there are actually 1280 bytes of image data, which can then be decoded to the image above.

这篇关于解码Z64(ZB64)字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆