如何压缩字符串?

发布于 2024-09-18 00:23:55 字数 290 浏览 4 评论 0原文

我希望对某种类型的字符串进行可逆压缩,以便我可以将其包含在 URL 中,而无需跟踪它所指的内容。我想要压缩的字符串是 SVG 路径字符串,这里有一个简短的入门: http://apike.ca/prog_svg_paths .html

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

如果有人知道这方面的好资源,我们将不胜感激!

贾森

I would like to have a reversible compression for a type of string so that i can include it in URLs without keeping track of what it refers to. The string i would like to compress is SVG path string, here is a short primer: http://apike.ca/prog_svg_paths.html

Basically, the string contains a character, followed by arbitrary number of integers, then another character followed by arbitrary number of integers and so on.

If anyone knows of a good resource for this, it would be much appreciated!

Jason

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

总以为 2024-09-25 00:23:55

许多压缩算法都有详细的文档记录,其中一些甚至有 js 实现:

  • GZip A常见的(相当)好的压缩算法,我知道有一个 JS impl,我只是在寻找 URL

  • LZW 另一个问题指向 JS 中的 LZW 实现

  • 算术编码 (我这样做了,但是模型使用很愚蠢,因此无法达到最佳压缩率)

Many compression algorithms are well documented, a couple even have js implementations:

  • GZip A common (reasonably) good compression algorithm, I know there's a JS impl, i'm just hunting the URL

  • LZW Another question points to an LZW implementation in JS

  • Arithmetic coding (i did this, but the model it uses is stupid so doesn't achieve the best compression rates it could)

倦话 2024-09-25 00:23:55

以下解决方案返回压缩的 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))

顺便说一句...如果您担心 escape/unescape 被贬值,请考虑 polyfill

来自此处的LZW算法和来自此处

The following solution returns a compressed Base64 encoded string.

Create a file called zip.js with the code below and then see usage below that.

// 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)))
}

Usage:

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))

BTW... if you're concerned about escape/unescape being depreciated consider a polyfill

LZW algorithm from here and base64 encoding from here

寄风 2024-09-25 00:23:55

听起来您可能会受益于单 RLE 压缩和双 RLE 压缩。

有关这方面的入门知识可以在这里看到:

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

该库应该足够灵活,可以修改您的压缩模式到更可取的东西。该文章解释了这是如何工作的;可能是优化 SVG 案例的良好开端。

Sounds like you might benefit from single and double RLE compression.

A primer on this can be seen here:

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

The library should be flexible enough to modify your compression pattern to something more preferable. The writeup explains how this works; might be a good start to optimize your SVG case.

寻梦旅人 2024-09-25 00:23:55

您可以尝试霍夫曼压缩。不同字符的数量为20-30,如果字符串很长,压缩应该有效。

You could try Huffman compression. Number of different chars is 20-30, and if the string is long, compression should be effective.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文