java:如何获取压缩字节数组的字符串表示形式?
我想将一些压缩数据放入远程存储库。
为了将数据放入此存储库,我只能使用一种将资源名称及其内容作为字符串的方法。 (如 data.txt + “hello world”)。
存储库正在模拟文件系统,但事实并非如此,因此我无法直接使用文件。
我希望能够执行以下操作:
- 客户端向服务器发送文件“data.txt”
- 服务器将“data.txt”压缩为压缩文件“data.zip”
- 服务器将 data.zip 的字符串表示形式发送到存储库
- 存储库存储 data.zip
- 客户端从存储库 data.zip 下载,并且他能够使用其最喜欢的 zip 工具打开它
当我尝试获取压缩文件的字符串表示形式时,问题出现在步骤 3 中。
这是一个示例类,使用 zip*stream 并模拟展示我的问题的存储库。
创建的 zip 文件可以正常工作,但在“序列化”后它已损坏。
(示例类使用 jakarta commons.io )
非常感谢您的帮助。
package zip;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
/**
* Date: May 19, 2010 - 6:13:07 PM
*
* @author Guillaume AME.
*/
public class ZipMe {
public static void addOrUpdate(File zipFile, File ... files) throws IOException {
File tempFile = File.createTempFile(zipFile.getName(), null);
// delete it, otherwise you cannot rename your existing zip to it.
tempFile.delete();
boolean renameOk = zipFile.renameTo(tempFile);
if (!renameOk) {
throw new RuntimeException("could not rename the file " + zipFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
}
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
boolean notInFiles = true;
for (File f : files) {
if (f.getName().equals(name)) {
notInFiles = false;
break;
}
}
if (notInFiles) {
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(name));
// Transfer bytes from the ZIP file to the output file
int len;
while ((len = zin.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
entry = zin.getNextEntry();
}
// Close the streams
zin.close();
// Compress the files
if (files != null) {
for (File file : files) {
InputStream in = new FileInputStream(file);
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(file.getName()));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
}
tempFile.delete();
out.close();
}
public static void main(String[] args) throws IOException {
final String zipArchivePath = "c:/temp/archive.zip";
final String tempFilePath = "c:/temp/data.txt";
final String resultZipFile = "c:/temp/resultingArchive.zip";
File zipArchive = new File(zipArchivePath);
FileUtils.touch(zipArchive);
File tempFile = new File(tempFilePath);
FileUtils.writeStringToFile(tempFile, "hello world");
addOrUpdate(zipArchive, tempFile);
//archive.zip exists and contains a compressed data.txt that can be read using winrar
//now simulate writing of the zip into a in memory cache
String archiveText = FileUtils.readFileToString(zipArchive);
FileUtils.writeStringToFile(new File(resultZipFile), archiveText);
//resultingArchive.zip exists, contains a compressed data.txt, but it can not
//be read using winrar: CRC failed in data.txt. The file is corrupt
}
}
I want to put some compressed data into a remote repository.
To put data on this repository I can only use a method that take the name of the resource and its content as a String. (like data.txt + "hello world").
The repository is moking a filesystem but is not, so I can not use File directly.
I want to be able to do the following:
- client send to server a file 'data.txt'
- server compress 'data.txt' into a compressed file 'data.zip'
- server send a string representation of data.zip to the repository
- repository store data.zip
- client download from repository data.zip and his able to open it with its favorite zip tool
The problem arise at step 3 when I try to get a string representation of my compressed file.
Here is a sample class, using the zip*stream and that emulate the repository showcasing my problem.
The created zip file is working, but after its 'serialization' it's get corrupted.
(the sample class use jakarta commons.io )
Many thanks for your help.
package zip;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
/**
* Date: May 19, 2010 - 6:13:07 PM
*
* @author Guillaume AME.
*/
public class ZipMe {
public static void addOrUpdate(File zipFile, File ... files) throws IOException {
File tempFile = File.createTempFile(zipFile.getName(), null);
// delete it, otherwise you cannot rename your existing zip to it.
tempFile.delete();
boolean renameOk = zipFile.renameTo(tempFile);
if (!renameOk) {
throw new RuntimeException("could not rename the file " + zipFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
}
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
boolean notInFiles = true;
for (File f : files) {
if (f.getName().equals(name)) {
notInFiles = false;
break;
}
}
if (notInFiles) {
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(name));
// Transfer bytes from the ZIP file to the output file
int len;
while ((len = zin.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
entry = zin.getNextEntry();
}
// Close the streams
zin.close();
// Compress the files
if (files != null) {
for (File file : files) {
InputStream in = new FileInputStream(file);
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(file.getName()));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
}
tempFile.delete();
out.close();
}
public static void main(String[] args) throws IOException {
final String zipArchivePath = "c:/temp/archive.zip";
final String tempFilePath = "c:/temp/data.txt";
final String resultZipFile = "c:/temp/resultingArchive.zip";
File zipArchive = new File(zipArchivePath);
FileUtils.touch(zipArchive);
File tempFile = new File(tempFilePath);
FileUtils.writeStringToFile(tempFile, "hello world");
addOrUpdate(zipArchive, tempFile);
//archive.zip exists and contains a compressed data.txt that can be read using winrar
//now simulate writing of the zip into a in memory cache
String archiveText = FileUtils.readFileToString(zipArchive);
FileUtils.writeStringToFile(new File(resultZipFile), archiveText);
//resultingArchive.zip exists, contains a compressed data.txt, but it can not
//be read using winrar: CRC failed in data.txt. The file is corrupt
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Zip 文件是二进制的。 Java 中的字符串处理是文本性的,可能会破坏 CRLF、零字节和 EOF 标记等内容。当涉及到读取和重写 zip 文件时,我建议您尝试使用
readFileToByteArray
和writeByteArrayToFile
作为实验。如果这有效,那么我怀疑字符串处理是罪魁祸首。Zip files are binary. String handling in Java is textual and might be mangling what it sees as CRLFs, zero bytes and EOF markers. When it comes to reading and rewriting the zipfile, I suggest you try with
readFileToByteArray
andwriteByteArrayToFile
as an experiment. If that works then I'd suspect the String handling is to blame.因此您想要获取 zip(即二进制)流的字符串(即文本)表示形式。
Base64 是最流行的方法。
一种流行的 Java 实现来自 Apache commons(编解码器组件)
So you want to get a string (i.e. textual) representation of a zip (i.e. binary) stream.
Base64 is the most popular way to do this.
One popular Java implementation is from Apache commons (codec component)