无法正确转换 Base64 字符串和解压缩
Can not convert Base64 String and unGzip it properly
我有 Base64 字符串。我正在尝试解码它,然后解压缩它。
String textToDecode = "H4sIAAAAAAAAAAEgAN//0JTQtdGC0LDQu9C40LfQuNGA0L7QstCw0L3QvdGL0LmRCuyiIAAAAA==\n";
byte[] data = Base64.decode(textToDecode, Base64.DEFAULT);
String result = GzipUtil.decompress(data);
我用来解压的代码:
public static String decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}
我应该得到这个字符串:
Детализированный
结果,我得到了这个带有问号符号的字符串:
Детализирован��ый
我的错误是什么?以及如何解决?
可能是这里的问题:
string.append(new String(data, 0, bytesRead))
您正在使用默认字符编码将字节解码为 Java 字符串。如果(当前)默认编码与将原始字符编码为字节(压缩之前等)时使用的编码不同,那么您可能会得到无法正确解码的字节。然后解码器将用解码器的替换字符替换它们;即默认 '\uFFFD'
。
如果这是问题所在,那么解决方案是找出正确的字符编码并使用 String(byte[], int, int, Charset)
创建 String
.
一个问题是,当从字节转换为字符串(内部 Unicode)时
没有给出编码。对于像 UTF-8 这样的多字节编码,不能采用固定数量的字节(如 32),然后在最后得到一个有效序列。
您显然丢失了一半序列。因此编码可能是UTF-8。
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
baos.write(data, 0, bytesRead);
}
gis.close();
return baos.toString("UTF-8"); // Or "Windows-1251" ...
上面解决了buffer boundary的问题,并且指定了编码方式,所以同样的代码在不同的电脑上运行。
和思想:
new String(bytes, encoding)
string.getBytes(encoding)
如果您只使用流可以避免编码问题,这几行代码应该可以很好地完成工作
public static String decompress(byte[] compressed) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
try (GZIPInputStream gis = new GZIPInputStream(
new ByteArrayInputStream(compressed))) {
org.apache.commons.compress.utils.IOUtils.copy(gis, bos);
}
return bos.toString();
}
}
我有 Base64 字符串。我正在尝试解码它,然后解压缩它。
String textToDecode = "H4sIAAAAAAAAAAEgAN//0JTQtdGC0LDQu9C40LfQuNGA0L7QstCw0L3QvdGL0LmRCuyiIAAAAA==\n";
byte[] data = Base64.decode(textToDecode, Base64.DEFAULT);
String result = GzipUtil.decompress(data);
我用来解压的代码:
public static String decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}
我应该得到这个字符串:
Детализированный
结果,我得到了这个带有问号符号的字符串:
Детализирован��ый
我的错误是什么?以及如何解决?
可能是这里的问题:
string.append(new String(data, 0, bytesRead))
您正在使用默认字符编码将字节解码为 Java 字符串。如果(当前)默认编码与将原始字符编码为字节(压缩之前等)时使用的编码不同,那么您可能会得到无法正确解码的字节。然后解码器将用解码器的替换字符替换它们;即默认 '\uFFFD'
。
如果这是问题所在,那么解决方案是找出正确的字符编码并使用 String(byte[], int, int, Charset)
创建 String
.
一个问题是,当从字节转换为字符串(内部 Unicode)时 没有给出编码。对于像 UTF-8 这样的多字节编码,不能采用固定数量的字节(如 32),然后在最后得到一个有效序列。
您显然丢失了一半序列。因此编码可能是UTF-8。
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
baos.write(data, 0, bytesRead);
}
gis.close();
return baos.toString("UTF-8"); // Or "Windows-1251" ...
上面解决了buffer boundary的问题,并且指定了编码方式,所以同样的代码在不同的电脑上运行。
和思想:
new String(bytes, encoding)
string.getBytes(encoding)
如果您只使用流可以避免编码问题,这几行代码应该可以很好地完成工作
public static String decompress(byte[] compressed) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
try (GZIPInputStream gis = new GZIPInputStream(
new ByteArrayInputStream(compressed))) {
org.apache.commons.compress.utils.IOUtils.copy(gis, bos);
}
return bos.toString();
}
}