2011-08-20 74 views
3

我有一個數據字符串超過800個字符,我試圖壓縮下來使用QR碼(我想至少50%,但可能會很高興,如果我得到它少於七個百)。以下是我正在試圖壓縮的示例串,包含841個字符:字符串比DotNetZip或LZMA有更好的壓縮庫嗎?

+hgoSuJm2ecydQj9mXXzmG6b951L2KIl0k9VGzIEtLztuWO2On9rt7DUlH0lXzG4iJ1yK0fA 
97mDyclKSttIZXOxSPBf85LEN4PUUqj65aio5qwZttZSZ64wpnMFg/7Alt1R39IJvTmeYfBm 
Tuc1noMMcknlydFocwI8/sk2Sje5MR/nYNX0LPkQhzyi5vFJdrndqAgXYULsYrB3TJDAwvgs 
Kw9C5EJnrlqcb21zg17O2gU/C8KY0pz9RPzUl1Sb0rCP8iZCeis4YbQ5tuUppOfnO/X0Mosv 
SOQJ/bF9juKW8ocnQvNjsNxGV1gPkWWtiU2Old7Qm7FLDqL6kQKrq356yifs0NiMVGdvAg32 
eugewuttCugoZASYOpQdwPu1jMxVO1fzF3zEy5w6tDlcfA2DZwa+un9/k8XZWAO/KVExy68q 
UtVRQxsIOKgpl/2tNw5DBAKbykKIkmizbsA2xtzqnYqld4kOdNMJh3YjlqWF9Bt8MZo7a+Q6 
jgayr2rjpyIptc599DGtvp68ZNQ64TKNmiMnnyGMo3E+xW34G3RrsYnHGm+xJoLKoOJhacDu 
oZke1ycJgQv+Y61WPrvtFOVBxV5rvSzO0+8px5AWN3uCrrw1RmT5N14IVhh6BOtRjsifqIB2 
dAKxzBNsvbXm1SzkuyqYiMnp5ivy3m2mPwc9GLsykx0FRIkhCYO8ins9E5ot9QvVnE155MFA 
8FVwsP5uNdOF4EzQS2/h2QK3zb5Yq4Nftlo605Dd5vuVN/A7CUN38DaAKBxDKgqDzydfQnZw 
R0hTfMHNLgBJKNDSpz2P6almGlUJtXT6IYmzuU2Iaion8ePG 

我已經嘗試了以下三個庫:

  1. 內置.NET GzipStream
  2. DotNetZip,其中,
    • GzipStream
    • DeflateStream
  3. 的LZMA SDK 7-ZIP

我遇到一個問題,即壓縮實際進行串。我的理解是DeflateStream的開銷最小,但它仍然在添加字符。使用DotNetZip,我告訴它使用最大壓縮:

Imports Ionic.Zlib 

Shared Function CompressData(data As Byte()) As Array 

    Dim msCompressed As MemoryStream = New MemoryStream 

    ' I'm not sure if the last parameter on this next function should be 
    ' true (for LeaveOpen), but it doesn't seem to affect it either way. 
    Dim deflated As DeflateStream = New DeflateStream(msCompressed, _ 
     CompressionMode.Compress, CompressionLevel.BestCompression, True) 

    ' Write data to compression stream (which is linked to the memorystream) 
    deflated.Write(data, 0, data.Length) 
    deflated.Flush() 
    deflated.Close() 

    Return msCompressed.ToArray 
End Function 

我只是在想這會變得更糟,因爲我將不得不甚至更多數據。有這個長度的字符串有更好的壓縮算法嗎?壓縮通常只能在較長的字符串上工作嗎?不幸的是,數據是這樣的,我不能使用替代字符作爲數據片段。

此外,我能夠使用字母數字編碼的QR碼,或者我必須使用二進制?根據http://www.qrme.co.uk/qr-code-forum.html?func=view&catid=3&id=324,我不認爲我可以,但我想確定一下。

感謝您的幫助!

+1

我認爲你正在做的是轉換二進制 - >字符串 - >壓縮 - >字符串QR。您應該跳過第一個字符串轉換部分。 – LostInComputer

+0

我嘗試刪除第一個字符串轉換,但我沒有看到任何更改。也就是說,我用原始數據創建了一個字符串。這些數據被傳遞給一個子程序,並以字節數組的形式返回。然後將這個字節數組傳遞給壓縮算法,該算法也返回一個字節數組。我現在將壓縮的字節數組和未壓縮的字節數組轉換爲字符串來比較長度。無論哪個字符串較短,都會傳遞給QR碼庫,因爲它需要一個字符串進行編碼。感謝您的建議! –

回答

3

乍一看,似乎您試圖採取一些數據,並在這個過程中轉換成一個QR碼:

- >加密 - >使用Base64編碼 - >壓縮 - >作二維碼。

我建議使用這種方法來代替:

- >壓縮 - >加密 - >使QR碼。

當你想加密和壓縮,幾乎每個人都建議壓縮,然後加密。 。 (因爲加密與壓縮數據的工作方式以及與未壓縮數據 但壓縮通常使明文短和加密文件不再 有關詳細信息,請參閱: 「​​」 「Compress and then encrypt, or vice-versa?」 「Composing Compression and Encryption」 「Compress, then encrypt tapes 「 」 Is it better to encrypt a message and then compress it or the other way around? Which provides more security? 「 」 Compressing and Encrypting files on Windows 「 」 Encryption and Compression 「 」 Do encrypted compression containers like zip and 7z compress or encrypt first? 「 」 When compressing and encrypting, should I compress first, or encrypt first?」, 等)

「我能夠使用字母數字編碼的二維碼,還是我必須使用二進制?」

大多數加密算法產生二進制輸出,因此將其直接轉換爲二進制編碼的QR碼將是最簡單的。 我想你可以以某種方式將加密數據轉換爲QR字母數字編碼可以處理的東西,但爲什麼?

「有沒有一些更好的壓縮算法」

對於加密的數據,不,它是(幾乎可以肯定)不可能壓縮以及加密的數據,不管你用什麼算法。

如果按照建議進行壓縮然後加密,那麼各種壓縮算法的有效性取決於特定種類的輸入數據,而不取決於壓縮後您對它執行的操作。

什麼樣的數據是你的輸入數據?

如果,假設,輸入數據是一些簡短的ASCII文本, 也許你可以使用在 「Really simple short string compression」 「Best compression algorithm for short text strings」 「Compression of ASCII strings in C」 「Twitter text compression challenge」中提到的壓縮算法之一。

另一方面,如果您的輸入數據是某種照片 或許您可以使用「Twitter image encoding challenge」中提到的許多壓縮算法之一。

2

壓縮通過去除數據中的冗餘來工作,但字符串似乎包含隨機/加密數據,因此沒有冗餘來刪除。

但是,它是使用base-64編碼的數據,所以每個字符只能傳送6位信息。如果保留二進制數據而不是base-64編碼,則只有631個字節。

+0

我如何將它保存爲二進制數據?我使用的QR碼庫(MessagingToolkit.QRCode)將數據編碼爲字符串。我不需要將字節數組轉換爲字符串來將其編碼爲QR碼嗎? (對不起,我的無能爲力。)是否有一些機制保持它作爲二進制數據,同時仍然使它成爲一個字符串?我一直在byte數組上使用Convert.ToBase64String來創建一個可以被編碼的字符串。我會如何按照你的建議去做?謝謝! –

+0

QR代碼支持二進制,所以這將是您使用的庫中的限制。無論如何,你會更好'二進制 - >壓縮 - > base64 - >字符串而不是'二進制 - > base64 - >字符串 - >二進制 - >壓縮 - >二進制 - > base64 - >字符串。 – Guffa

+0

如果你沒有使用二進制,base64的數量並不理想。 Base64包含小寫字母,QR字符集中不包含字母數字,因此編碼器仍將使用每base64字符8位,因此您丟掉兩位。 – smparkes

3

這個答案與Guffa的答案有關。他說QR碼可以接受二進制數據,它必須是你使用的庫的一個限制。

我看了一下庫的源代碼。你調用編碼功能吧?這是編碼功能的內容

public virtual Bitmap Encode(String content, Encoding encoding) 
{ 
    bool[][] matrix = calQrcode(encoding.GetBytes(content)); 
    SolidBrush brush = new SolidBrush(qrCodeBackgroundColor); 
    Bitmap image = new Bitmap((matrix.Length * qrCodeScale) + 1, (matrix.Length * qrCodeScale) + 1); 
    Graphics g = Graphics.FromImage(image); 
    g.FillRectangle(brush, new Rectangle(0, 0, image.Width, image.Height)); 
    brush.Color = qrCodeForegroundColor ; 
    for (int i = 0; i < matrix.Length; i++) 
    { 
     for (int j = 0; j < matrix.Length; j++) 
     { 
      if (matrix[j][i]) 
      { 
       g.FillRectangle(brush, j * qrCodeScale, i * qrCodeScale, qrCodeScale, qrCodeScale); 
      } 
     } 
    } 
    return image; 
} 

第一行(encoding.GetBytes(content))將字符串轉換爲字節。

獲取然後將源代碼修改它有這樣的功能:「公共虛擬位圖編碼(字節[]的內容)」

2

您正在比較不同的壓縮機。 Zip系列通常使用統計壓縮,而LZ系列是Lempel-Ziv的縮寫,它是一種字典壓縮,用於消除輸入文本中的冗餘。所以,壓縮通過去除超多的信息起作用。它適用於文本文件和圖像,對音頻,視頻和程序文件不太好。對於後者,存在有損壓縮,但不適用於程序文件。考慮到你的例子字符串,它包含了太多的熵來壓縮。您可以使用-log(p)+ log(2)計算信息熵,其中p是文本中出現的字符的概率。另見信息論和香農定理。

+0

可以從[提問者之前的問題之一]中猜到(http://stackoverflow.com/questions/6448226/using-rjindael-and-rsa-to-encrypt-data-stored-in-qr-code-in -visual-basic-net)數據是以加密形式存在的,因此數據預計將包含高熵,並且有損壓縮算法會對加密數據造成危害。 –

+0

沒有upvote?你明白我寫的是什麼嗎?我不認爲我已經和你說過話,因爲我沒有建議我寫了BUT NOT FOR PROGRAMS FILES的有損壓縮。我應該澄清這一點嗎? – Bytemain

+0

對不起,我誤解了「程序文件」是指程序,即包含機器代碼的文件。按照我的理解,提問者給出的加密數據既不是文本,圖像,音頻,視頻,也不是「程序文件」。 –