Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中压缩字符串?_Java_String_Compression_Zip - Fatal编程技术网

如何在Java中压缩字符串?

如何在Java中压缩字符串?,java,string,compression,zip,Java,String,Compression,Zip,我使用GZIPOutputStream或zipoutpstream压缩字符串(我的String.length()小于20),但压缩结果比原始字符串长 在某个网站上,我发现一些朋友说这是因为我原来的字符串太短,GZIPOutputStream可以用来压缩更长的字符串 有人能帮我压缩字符串吗 我的功能是: String compress(String original) throws Exception { } 更新: import java.io.ByteArrayOutputStream;

我使用
GZIPOutputStream
zipoutpstream
压缩字符串(我的
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));
    }
}
结果是:


你的朋友是对的。gzip和ZIP都基于。这是一种通用算法,不用于编码小字符串

如果需要,一种可能的解决方案是自定义编码和解码
HashMap
。这可以让您进行简单的一对一映射:

HashMap<String, String> toCompressed, toUncompressed;

String compressed = toCompressed.get(uncompressed);
// ...
String uncompressed = toUncompressed.get(compressed);
HashMap压缩,toUncompressed;
String compressed=toCompressed.get(未压缩);
// ...
String uncompressed=toUncompressed.get(compressed);

显然,这需要设置,并且只适用于少量字符串。

可能会有所帮助,但只有在创建字符串时,如果小字符串中有大量常用字符,才可以将其视为字符列表,这意味着对于字符串中的每个字符,您需要支持char的所有可能值。来自太阳

字符:字符数据类型是单个16位Unicode字符。它的最小值为“\u0000”(或0),最大值为“\uffff”(或65535)

如果您想要支持一组简化的字符,可以编写一个简单的压缩算法,类似于二进制->十进制->十六进制转换。从65536(或目标系统支持的字符数)到26(字母顺序)/36(字母数字)等等


我已经使用过这个技巧好几次了,例如,将时间戳编码为文本(目标36+,源10)-只要确保有大量的单元测试

您看不到对字符串进行任何压缩,因为您至少需要几百个字节才能使用GZIPOutputStream或zipoutpstream进行真正的压缩。你的字符串太小了。(我不明白你为什么要压缩相同的字符串)

检查由此得出的结论:

本文还展示了如何压缩 并实时解压缩数据 为了减少网络流量和 提高您的应用程序的性能 客户端/服务器应用程序。 但是,动态压缩数据, 提高的性能 仅当 被压缩的对象更复杂 而不是几百个字节。你 无法观察到 如果 正在压缩和删除的对象 它们是简单的字符串对象, 比如说


压缩算法几乎总是有某种形式的空间开销,这意味着它们只有在压缩的数据足够大,以至于开销小于节省的空间量时才有效


压缩一个只有20个字符长的字符串并不容易,而且也不总是可能的。如果有重复,哈夫曼编码或简单的游程编码可能能够压缩,但可能不会压缩太多。

压缩算法是和的组合。您可以单独使用其中一种算法

压缩基于两个因素:

  • 原始链中子字符串的重复(LZW):如果有大量重复,压缩将是有效的。该算法对于压缩长文本具有良好的性能,因为单词经常重复
  • 压缩链中每个字符的数量(哈夫曼):字符之间的重新分配越不平衡,压缩效率就越高
在您的情况下,您应该只尝试LZW算法。基本上,可以在不添加元信息的情况下压缩链:短字符串压缩可能更好


对于哈夫曼算法,编码树必须与压缩文本一起发送。因此,对于小文本,由于树的原因,结果可能比原始文本大。

哈夫曼编码是一个明智的选择。Gzip和friends会这样做,但他们的工作方式是为输入构建一个哈夫曼树,发送该树,然后发送用该树编码的数据。如果树相对于数据较大,则可能没有不保存的大小


但是,可以避免发送树:相反,您可以安排发送方和接收方已经有一棵树。它不能专门为每个字符串构建,但可以使用一个全局树对所有字符串进行编码。如果您使用与输入字符串相同的语言(英语或其他任何语言)构建它,您应该仍然能够获得良好的压缩,尽管不如为每个输入使用自定义树。

如果密码或多或少是“随机”的,那么您的运气就不好了,您将无法获得显著的大小缩减


但是:为什么需要压缩密码?也许你需要的不是压缩,而是某种散列值?如果只需要检查名称是否与给定密码匹配,则不需要保存密码,但可以保存密码的哈希。要检查键入的密码是否与给定的名称匹配,可以使用相同的方法生成哈希值,并将其与保存的哈希值进行比较。由于散列(Object.hashCode())是一个整数,因此您可以在80字节内存储所有20个密码散列)。

看看哈夫曼算法

其思想是,根据每个字符在文本中的频率(频率越高,序列越小),用位序列替换每个字符

您可以阅读全文并构建代码表,例如:

符号代码

a 0

s 10

E110

m 111

该算法生成一个符号
byte[] bytes = string.getBytes("UTF-8");
private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
...
String s = new String(bytes, UTF8_CHARSET);