让我解释一下:在我的用例中,一个系统会给我许多大小不同(字符数;长度)的字符串,有时它会非常大!问题是我必须将这个字符串保存在"SQL Server"数据库表的一列中,坏消息是我不允许在此数据库中进行任何迁移,好消息是该列已经有了类型nvarchar(max)
.
我之前做过一些研究,并在下面的帖子中使用"Gzip"和"Brotli"编写了一个数据压缩器.
https://khalidabuhakmeh.com/compress-strings-with-dotnet-and-csharp
var value = "hello world";
var level = CompressionLevel.SmallestSize;
var bytes = Encoding.Unicode.GetBytes(value);
await using var input = new MemoryStream(bytes);
await using var output = new MemoryStream();
// GZipStream with BrotliStream
await using var stream = new GZipStream(output, level);
await input.CopyToAsync(stream);
var result = output.ToArray();
var resultString = Convert.ToBase64String(result);
在实现了转换方法之后,我创建了生成不同大小(长度)的随机字符串的测试,以验证压缩器的性能,此时我注意到以下几点."Gzip"和"Brotli"都首先转换为字节[](字节数组),然后应用压缩,这会产生一个按预期大小缩小的结果向量(字节数组),但随后将结果(字节[])转换为一个基64字符串,在100%的测试中,该字符串的字符(长度)比初始字符串多.
我的随机字符串生成器:
var rd_char = new Random();
var rd_length = new Random();
var wordLength = rd_length.Next(randomWordParameters.WordMinLength, randomWordParameters.WordMaxLength);
var sb = new StringBuilder();
int sourceNumber;
for (int i = 0; i < wordLength; i++)
{
sourceNumber = rd_char.Next(randomWordParameters.CharLowerBound, randomWordParameters.CharUpperBound);
sb.Append(Convert.ToChar(sourceNumber));
}
var word = sb.ToString();
我的示例字符串并不完全包含手头 case 的完美表示,但我相信它们已经足够好了.这里是字符串生成器方法,实际上它在给定的大小范围内生成完全随机的字符串,我在测试中使用了33~127个值中提供的字符传递给皈依者.ToChar()方法.系统提供的字符串是JSON格式的,实际上它们是URL列表(有上万个URL),URL通常具有随机字符序列,因此我try 尽可能随机地生成字符串.
事实是,考虑到我试图在数据库中保存一个字符串的情况,该字符串最初(在压缩之前)大于列中允许的最大大小(长度),在数据库中保存时,出现问题的表的列中的"数据"是压缩后生成的结果"base 64"字符串,而不是缩减的大小向量(字节数组),我相信数据库会拒绝这个字符串(以64为基数),因为它的长度(以字符数计)大于原始字符串的长度.
所以我的问题是,有没有(可逆的)方法把一个字符串转换成一个更小的字符串,当我说更小的时候,我的意思是"长度减少"?看来"Gzip"或"Brotli"并不能解决这个问题.
附言:我多次强调"长度"一词,以清楚地表明,在这一点上,我指的是文字的数量,而不是记忆中的长度,因为我在之前阅读的几个论坛中注意到,这种混淆使得很难得出结论.