如何将长字符串转换为短字符串,并且这是可逆操作。

huangapple go评论86阅读模式
英文:

How to convert a long string to a short one, and it is reversible operation

问题

我有一个来自Base64的长字符串,但它太长了,我该如何将其转换为一个短字符串?而且我希望这是一个可逆的操作,因为我想从短字符串中获取长字符串。
顺便说一下,我不想将这两个字符串保存到数据库中。

英文:

I have a long string from Base64, but it is too long, how can I covert it to a short one. And I want it is a reversible operation, as I want to get the long one from the short one.
By the way, I do not want to save these two strings to database.

答案1

得分: 7

将任意长的字符串转换为任意短的字符串在一般情况下是不可能的,这是由于鸽巢原理的限制:

  • 可逆性意味着转换的值域(小字符串)至少需要与转换的定义域(大字符串)一样多的元素,
  • 存在比短字符串更多的不同长字符串。

类比整数,考虑将一个3位数(900种可能性)转换为一个2位数(90种可能性)并且仍然可逆,这是不可能的,因为90 < 900。

然而,如果长字符串是可预测的并且具有很多冗余,你可以尝试应用无损压缩算法(如gzip),以便在常见情况下缩短字符串。

Pigeonhole principle:鸽巢原理的维基百科链接。

英文:

Converting arbitrary long strings to arbitrary short strings is not possible in general because of the Pigeonhole principle:

  • reversibility implies that the conversion codomain (small strings) needs to be have at least as many elements as the conversion domain (large strings),
  • there exist vastly more distinct long strings than distinct short strings.

As an analogy with integers, consider that it is not possible to convert a 3-digit number (900 possibilities) into a 2-digit number (90 possibilities) and still be reversible, as 90 < 900.

However, if the long string is predictable and has a lot of redundancy, you may try to apply a lossless compression algorithm like gzip, in order to shorten it in the common case.

答案2

得分: 0

Base64编码和解码确实是可逆的操作。解码后的字符串较短,因此在某些情况下(并非总是如此)传输和存储可能更便宜。

标准库中的base64包提供了一切你需要的功能,可以轻松将“长”Base64编码的字符串解码为原始解码字符串,解码后的字符串大约会缩短25%:

decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
	fmt.Println("error:", err)
}

你可以在Playground中尝试这个代码:

请注意,Base64格式存在多种变体,因此你需要确切地知道使用的是哪种格式进行编码,并使用相同的格式进行解码。base64.StdEncoding是RFC 4648的变体。

英文:

Base64 encoding and decoding are indeed reversible operations. The decoded string is shorter, so it may be cheaper to transfer and store in some cases (not always, YMMV).

The base64 package in the standard library has everything you need to easily decode the "long" Base64 encoded string into the original decoded string, roughly 25% shorter:

decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
	fmt.Println(&quot;error:&quot;, err)
}

You can try this in the Playground:

Note that there exists several variants of the Base64 format, so you need to know exactly which one was used to encode, and use the same to decode. base64.StdEncoding is the variant RFC 4648.

答案3

得分: 0

下面是我为您翻译的代码:

package main

import (
	"bytes"
	"compress/gzip"
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/gin-gonic/gin"
)

type User struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

func main() {
	r := gin.Default()

	// 使用GZIP压缩JSON数据的端点
	r.POST("/compress", func(c *gin.Context) {
		var user User
		if err := c.BindJSON(&user); err != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "无效的JSON"})
			return
		}

		jsonData, err := json.Marshal(user)
		if err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "JSON编码失败"})
			return
		}

		var buf bytes.Buffer
		gz := gzip.NewWriter(&buf)
		if _, err := gz.Write(jsonData); err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "GZIP压缩失败"})
			return
		}
		if err := gz.Close(); err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "GZIP写入器关闭失败"})
			return
		}

		c.Data(http.StatusOK, "application/octet-stream", buf.Bytes())
	})

	// 解压GZIP压缩的JSON数据的端点
	r.POST("/decompress", func(c *gin.Context) {
		data, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "读取请求体失败"})
			return
		}

		var buf bytes.Buffer
		buf.Write(data)

		gz, err := gzip.NewReader(&buf)
		if err != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "无效的GZIP格式"})
			return
		}
		defer gz.Close()

		decompressedData, err := ioutil.ReadAll(gz)
		if err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "GZIP解压失败"})
			return
		}

		var user User
		if err := json.Unmarshal(decompressedData, &user); err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "JSON解码失败"})
			return
		}

		c.JSON(http.StatusOK, user)
	})

	// 运行服务器
	if err := r.Run(":8080"); err != nil {
		panic(err)
	}
}

希望对您有帮助!如果您有任何其他问题,请随时问我。

英文:

The next code in GoLang worked for me:

package main
import (
&quot;bytes&quot;
&quot;compress/gzip&quot;
&quot;encoding/json&quot;
&quot;io/ioutil&quot;
&quot;net/http&quot;
&quot;github.com/gin-gonic/gin&quot;
)
type User struct {
Name  string `json:&quot;name&quot;`
Email string `json:&quot;email&quot;`
}
func main() {
r := gin.Default()
// Endpoint to compress JSON data using GZIP
r.POST(&quot;/compress&quot;, func(c *gin.Context) {
var user User
if err := c.BindJSON(&amp;user); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;invalid json&quot;})
return
}
jsonData, err := json.Marshal(user)
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;json marshalling failed&quot;})
return
}
var buf bytes.Buffer
gz := gzip.NewWriter(&amp;buf)
if _, err := gz.Write(jsonData); err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;gzip compression failed&quot;})
return
}
if err := gz.Close(); err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;gzip writer close failed&quot;})
return
}
c.Data(http.StatusOK, &quot;application/octet-stream&quot;, buf.Bytes())
})
// Endpoint to decompress GZIP compressed JSON data
r.POST(&quot;/decompress&quot;, func(c *gin.Context) {
data, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;failed to read request body&quot;})
return
}
var buf bytes.Buffer
buf.Write(data)
gz, err := gzip.NewReader(&amp;buf)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;invalid gzip format&quot;})
return
}
defer gz.Close()
decompressedData, err := ioutil.ReadAll(gz)
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;gzip decompression failed&quot;})
return
}
var user User
if err := json.Unmarshal(decompressedData, &amp;user); err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;json unmarshalling failed&quot;})
return
}
c.JSON(http.StatusOK, user)
})
// Run the server
if err := r.Run(&quot;:8080&quot;); err != nil {
panic(err)
}
}

huangapple
  • 本文由 发表于 2021年8月6日 11:13:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/68675654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定