簡體   English   中英

如何壓縮字符串?

[英]How to compress a string?

我希望對一種字符串進行可逆壓縮,以便我可以將其包含在URL中,而無需跟蹤它所指的內容。 我要壓縮的字符串是SVG路徑字符串,這是一個簡短的引物: http//apike.ca/prog_svg_paths.html

基本上,字符串包含一個字符,后跟任意數量的整數,然后是另一個字符,后跟任意數量的整數,依此類推。

如果有人知道這是一個很好的資源,將不勝感激!

賈森

許多壓縮算法都有很好的文檔記錄,有幾個甚至有js實現:

  • GZip一個常見的(合理的)良好的壓縮算法,我知道有一個JS impl,我只是在搜索URL

  • LZW另一個問題指向JS中的LZW實現

  • 算術編碼 (我做了這個,但它使用的模型是愚蠢的,因此無法實現最佳壓縮率)

聽起來你可能會受益於單次和雙次RLE壓縮。

這里可以看到這方面的入門讀物:

http://pp19dd.com/2011/10/query-string-limits-encoding-hundreds-of-checkboxes-with-rle/#demo

該庫應該足夠靈活,可以將壓縮模式修改為更優選的模式。 該文章解釋了這是如何工作的; 可能是優化SVG案例的良好開端。

你可以嘗試Huffman壓縮 不同字符的數量是20-30,如果字符串很長,壓縮應該是有效的。

以下解決方案返回壓縮的Base64編碼字符串。

使用下面的代碼創建一個名為zip.js的文件,然后查看下面的用法。

// Apply LZW-compression to a string and return base64 compressed string.
export function zip (s) {
  try {
    var dict = {}
    var data = (s + '').split('')
    var out = []
    var currChar
    var phrase = data[0]
    var code = 256
    for (var i = 1; i < data.length; i++) {
      currChar = data[i]
      if (dict[phrase + currChar] != null) {
        phrase += currChar
      } else {
        out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0))
        dict[phrase + currChar] = code
        code++
        phrase = currChar
      }
    }
    out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0))
    for (var j = 0; j < out.length; j++) {
      out[j] = String.fromCharCode(out[j])
    }
    return utoa(out.join(''))
  } catch (e) {
    console.log('Failed to zip string return empty string', e)
    return ''
  }
}

// Decompress an LZW-encoded base64 string
export function unzip (base64ZippedString) {
  try {
    var s = atou(base64ZippedString)
    var dict = {}
    var data = (s + '').split('')
    var currChar = data[0]
    var oldPhrase = currChar
    var out = [currChar]
    var code = 256
    var phrase
    for (var i = 1; i < data.length; i++) {
      var currCode = data[i].charCodeAt(0)
      if (currCode < 256) {
        phrase = data[i]
      } else {
        phrase = dict[currCode] ? dict[currCode] : oldPhrase + currChar
      }
      out.push(phrase)
      currChar = phrase.charAt(0)
      dict[code] = oldPhrase + currChar
      code++
      oldPhrase = phrase
    }
    return out.join('')
  } catch (e) {
    console.log('Failed to unzip string return empty string', e)
    return ''
  }
}

// ucs-2 string to base64 encoded ascii
function utoa (str) {
  return window.btoa(unescape(encodeURIComponent(str)))
}
// base64 encoded ascii to ucs-2 string
function atou (str) {
  return decodeURIComponent(escape(window.atob(str)))
}

用法:

import { zip, unzip } from './zip'

// Zip a string
const str = 'zip it'
const base64CompressedString = zip(str)

// Zip an object
const obj = { a: 123, b: 'zipit' }
const base64CompressedString = zip(JSON.stringify(obj))

// Unzip the base64 compressed string back to an object.
const originalObject = JSON.parse(unzip(base64CompressedString))

順便說一句......如果你擔心逃避/ unescape被折舊,可以考慮使用polyfill

從LZW算法在這里和base64編碼從這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM