Reputation: 2953
I'm having a hard time trying to tar some files using the compress library.
My code is the following, and is taken from the commons.compress wiki exemples :
private static File createTarFile(String[] filePaths, String saveAs) throws Exception{
File tarFile = new File(saveAs);
OutputStream out = new FileOutputStream(tarFile);
TarArchiveOutputStream aos = (TarArchiveOutputStream) new ArchiveStreamFactory().createArchiveOutputStream("tar", out);
for(String filePath : filePaths){
File file = new File(filePath);
TarArchiveEntry entry = new TarArchiveEntry(file);
entry.setSize(file.length());
aos.putArchiveEntry(entry);
IOUtils.copy(new FileInputStream(file), aos);
aos.closeArchiveEntry();
}
aos.finish();
out.close();
return tarFile;
}
There is no error during the process, but when I try to untar the file, I got the following :
XXXX:XXXX /home/XXXX$ tar -xf typeCommandes.tar
tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
Also, the archive IS slighty smaller in size than the original file, which isnt normal for a tar, so there DO is a problem...
-rw-r--r-- 1 XXXX nobody 12902400 Jan 14 17:11 typeCommandes.tar
-rw-r--r-- 1 XXXX nobody 12901888 Jan 14 17:16 typeCommandes.csv
Anyone can tell me what I'm doing wrong ? Thanks
Upvotes: 2
Views: 12993
Reputation: 569
See also my answer here
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
public class TarUpdater {
private static final int buffersize = 8048;
public static void updateFile(File tarFile, File[] flist) throws IOException {
// get a temp file
File tempFile = File.createTempFile(tarFile.getName(), null);
// delete it, otherwise you cannot rename your existing tar to it.
if (tempFile.exists()) {
tempFile.delete();
}
if (!tarFile.exists()) {
tarFile.createNewFile();
}
boolean renameOk = tarFile.renameTo(tempFile);
if (!renameOk) {
throw new RuntimeException(
"could not rename the file " + tarFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
}
byte[] buf = new byte[buffersize];
TarArchiveInputStream tin = new TarArchiveInputStream(new FileInputStream(tempFile));
OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(tarFile.toPath()));
TarArchiveOutputStream tos = new TarArchiveOutputStream(outputStream);
tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
//read from previous version of tar file
ArchiveEntry entry = tin.getNextEntry();
while (entry != null) {//previous file have entries
String name = entry.getName();
boolean notInFiles = true;
for (File f : flist) {
if (f.getName().equals(name)) {
notInFiles = false;
break;
}
}
if (notInFiles) {
// Add TAR entry to output stream.
if (!entry.isDirectory()) {
tos.putArchiveEntry(new TarArchiveEntry(name));
// Transfer bytes from the TAR file to the output file
int len;
while ((len = tin.read(buf)) > 0) {
tos.write(buf, 0, len);
}
}
}
entry = tin.getNextEntry();
}
// Close the streams
tin.close();//finished reading existing entries
// Compress new files
for (int i = 0; i < flist.length; i++) {
if (flist[i].isDirectory()) {
continue;
}
InputStream fis = new FileInputStream(flist[i]);
TarArchiveEntry te = new TarArchiveEntry(flist[i],flist[i].getName());
//te.setSize(flist[i].length());
tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
tos.setBigNumberMode(2);
tos.putArchiveEntry(te); // Add TAR entry to output stream.
// Transfer bytes from the file to the TAR file
int count = 0;
while ((count = fis.read(buf, 0, buffersize)) != -1) {
tos.write(buf, 0, count);
}
tos.closeArchiveEntry();
fis.close();
}
// Complete the TAR file
tos.close();
tempFile.delete();
}
}
Upvotes: 0
Reputation: 21
Small correction to the code above. It does not close input stream, while Apache lib assumes that stream is managed by calling client. See the fix below (put this code after the line 'aos.putArchiveEntry(entry)') :
FileInputStream fis = new FileInputStream(fileForPuttingIntoTar);
IOUtils.copy(fis, aos);
fis.close();
aos.closeArchiveEntry();
Upvotes: 2
Reputation: 10321
the example here -> http://commons.apache.org/compress/examples.html uses the method putNextEntry(entry) which you seem to omit.
Upvotes: 0
Reputation: 30449
You're not closing the TarArchiveOutputStream
. Add aos.close()
after aos.finish()
Upvotes: 4