我使用GZIPOutputStream
或ZIPOutputStream
来压缩字符串(我的string.length()
小于20),但压缩结果比原始字符串长。
在某些网站上,我发现有些朋友说这是因为我的原始字符串太短,GZIPOutputStream
可以用来压缩更长的字符串。
那么,有人可以帮我压缩一个字符串吗?
我的功能如下:
String compress(String original) throws Exception {
}
更新
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import java.util.zip.*;
//ZipUtil
public class ZipUtil {
public static String compress(String str) {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes());
gzip.close();
return out.toString("ISO-8859-1");
}
public static void main(String[] args) throws IOException {
String string = "admin";
System.out.println("after compress:");
System.out.println(ZipUtil.compress(string));
}
}
结果是:
答案 0 :(得分:37)
压缩算法几乎总是有某种形式的空间开销,这意味着它们只在压缩数据时才有效,这些数据足够大,开销小于节省的空间量。
压缩长度仅为20个字符的字符串并不容易,并不总是可行。如果你有重复,霍夫曼编码或简单的游程编码可能能够压缩,但可能不是很多。
答案 1 :(得分:9)
创建String时,可以将其视为char的列表,这意味着对于String中的每个字符,您需要支持char的所有可能值。来自太阳docs
char :char数据类型是一个16位Unicode字符。它的最小值为'\ u0000'(或0),最大值为'\ uffff'(或65,535(含))。
如果你想支持一组缩减的字符,你可以编写一个简单的压缩算法,类似于二进制 - >十进制 - >十六进制基数转换。您从65,536(或目标系统支持的多个字符)到26(字母)/ 36(字母数字)等。
我曾经多次使用过这个技巧,比如将时间戳编码为文本(目标36 +,源码10) - 只要确保你有足够的单元测试!
答案 2 :(得分:7)
如果密码或多或少是“随机”的,那么你运气不好,就无法大幅减少尺寸。
但是:为什么需要压缩密码?也许你需要的不是压缩,而是某种哈希值?如果您只需要检查名称是否与给定密码匹配,则不需要保存密码,但可以保存密码的哈希值。要检查键入的密码是否与给定名称匹配,您可以采用相同的方式构建哈希值,并将其与保存的哈希值进行比较。由于散列(Object.hashCode())是一个int,您将能够以80个字节存储所有20个密码哈希值。
答案 3 :(得分:6)
你的朋友是对的。 gzip和ZIP都基于DEFLATE。这是一种通用算法,不适用于编码小字符串。
如果您需要,可能的解决方案是自定义编码和解码HashMap<String, String>
。这可以让您进行简单的一对一映射:
HashMap<String, String> toCompressed, toUncompressed;
String compressed = toCompressed.get(uncompressed);
// ...
String uncompressed = toUncompressed.get(compressed);
显然,这需要设置,并且仅适用于少量字符串。
答案 4 :(得分:4)
Huffman Coding可能会有所帮助,但前提是你的小字符串中有很多频繁的字符
答案 5 :(得分:4)
ZIP算法是LZW和Huffman Trees的组合。您可以单独使用这些算法之一。
压缩基于2个因素:
在您的情况下,您应该只尝试LZW算法。基本上使用,链可以在不添加元信息的情况下进行压缩:对于短字符串压缩可能更好。
对于霍夫曼算法,编码树必须与压缩文本一起发送。因此,对于小文本,由于树,结果可能比原始文本大。
答案 6 :(得分:4)
霍夫曼编码是一个明智的选择。 Gzip和朋友这样做,但他们的工作方式是为输入构建一个Huffman树,发送它,然后发送用树编码的数据。如果树相对于数据较大,则可能没有节省大小。
但是,可以避免发送树:相反,您安排发送方和接收方已经拥有树。它不能专门为每个字符串构建,但您可以使用一个全局树来编码所有字符串。如果你使用与输入字符串(英语或其他)相同的语言构建它,你仍然应该得到良好的压缩,尽管不如每个输入的自定义树一样好。
答案 7 :(得分:0)
您没有看到您的String发生任何压缩,因为您至少需要几百个字节才能使用GZIPOutputStream或ZIPOutputStream进行实际压缩。你的字符串太小了。(我不明白为什么你需要压缩)
检查此article的结论:
文章还介绍了如何压缩 并在运行中解压缩数据 为了减少网络流量和 提高你的表现 客户/服务器应用程序 然而,动态压缩数据, 提高了性能 客户端/服务器应用程序仅在 被压缩的对象更多 超过几百个字节。您 无法观察到 如果改善性能 被压缩的对象和 转移是简单的String对象, 例如。
答案 8 :(得分:0)
看看霍夫曼算法。
https://codereview.stackexchange.com/questions/44473/huffman-code-implementation
这个想法是每个字符都被比特序列替换,这取决于它们在文本中的频率(频率越高,序列越小)。
您可以阅读整篇文章并构建代码表,例如:
符号代码
a 0
s 10
e 110
m 111
算法根据文本输入构建符号树。你拥有的角色种类越多,压缩效果就越差。
但根据你的文字,它可能是有效的。
答案 9 :(得分:0)