Scenario: Uncompress a tar file using Apache commons.
Problem: The tar i am using is a build tar which gets deployed into a web server. This tar contains duplicate entries like below.
appender_class.xml
APPENDER_CLASS.xml
when extracting using the below code only appender_class.xml is extracted but i want both the files how can i do that ? Renaming in fly is fine but how can i accomplish that?
public static void untar(File[] files) throws Exception {
String path = files[0].toString();
File tarPath = new File(path);
TarEntry entry;
TarInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new TarInputStream(new FileInputStream(tarPath));
while (null != (entry = inputStream.getNextEntry())) {
int bytesRead;
System.out.println("tarpath:" + tarPath.getName());
System.out.println("Entry:" + entry.getName());
String pathWithoutName = path.substring(0, path.indexOf(tarPath.getName()));
System.out.println("pathname:" + pathWithoutName);
if (entry.isDirectory()) {
File directory = new File(pathWithoutName + entry.getName());
directory.mkdir();
continue;
}
byte[] buffer = new byte[1024];
outputStream = new FileOutputStream(pathWithoutName + entry.getName());
while ((bytesRead = inputStream.read(buffer, 0, 1024)) > -1) {
outputStream.write(buffer, 0, bytesRead);
}
System.out.println("Extracted " + entry.getName());
}
}
Try opening your FileOutputstream like this instead:
File outputFile = new File(pathWithoutName + entry.getName());
for(int i = 2; outputFile.exists(); i++) {
outputFile = new File(pathWithoutName + entry.getName() + i);
}
outputStream = new FileOutputStream(outputFile);
It should generate a file called APPENDER_CLASS.xml2 if it encounters a previously created file called APPENDER_CLASS.xml. If a APPENDER_CLASS.xml2 exists it will create a APPENDER_CLASS.xml3, ad infinitum.
File.exists() takes case sensitivity into account (windows filenames are case insensitive, whereas unix, linux and mac are case sensitive). Thus with the above code on case insensitive filesystems the file would be renamed and on case sensitive filesystems the file would not be renamed.
Related
In my case I have to download images from the resources folder in my web app. Right now I am using the following code to download images through URL.
url = new URL(properties.getOesServerURL() + "//resources//WebFiles//images//" + imgPath);
filename = url.getFile();
is = url.openStream();
os = new FileOutputStream(sClientPhysicalPath + "//resources//WebFiles//images//" + imgPath);
b = new byte[2048];
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
But I want a single operation to read all images at once and create a zip file for this.
I don't know so much about the use of sequence input streams and zip input streams so if it is possible through these, please let me know.
The only way I can see you being able to do this is something like the following:
try {
ZipOutputStream zip = new ZipOutputStream(new FileOutputStream("C:/archive.zip"));
//GetImgURLs() is however you get your image URLs
for(URL imgURL : GetImgURLs()) {
is = imgURL.openStream();
zip.putNextEntry(new ZipEntry(imgURL.getFile()));
int length;
byte[] b = new byte[2048];
while((length = is.read(b)) > 0) {
zip.write(b, 0, length);
}
zip.closeEntry();
is.close();
}
zip.close();
}
Ref: ZipOutputStream Example
The url should return zip file. Else you have to take one by one and create a zip using your program
I currently have a function makeBackup() which zips an entire directory into a zip file, the files are however too big so we decided to switch to LZMA.
We found a library which does this (lzma-java) however it seems to compress only a single file, while the zip function we used permits to add files and directories to a zip file.
How can we implement the same with LZMA by changing our function? I added our current function below:
private static void makeBackup()
{
String backupPathString = "/home/backups";
/* zip remote file */
try
{
//name of zip file to create
String zipFilename = "backup.zip";
//create ZipOutputStream object
ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(zipFilename));
//path to the currentFile to be zipped
File zipFolder = new File(backupPathString);
//get path prefix so that the zip file does not contain the whole path
// eg. if currentFile to be zipped is /home/lalit/test
// the zip file when opened will have test currentFile and not home/lalit/test currentFile
int len = zipFolder.getAbsolutePath().lastIndexOf(File.separator);
String baseName = zipFolder.getAbsolutePath().substring(0, len + 1) + File.separator + "todaybackups";
zipFilesInPath(zipOutStream, backupPathString, baseName);
zipOutStream.flush();
zipOutStream.close();
}
catch (IOException e)
{
}
}
private static void zipFilesInPath(ZipOutputStream zipOutputStream, String filePath, String baseName) throws IOException
{
File currentFile = new File(filePath);
ArrayList<File> filesArrayList = new ArrayList<File>(Arrays.asList(currentFile.listFiles()));
if (filesArrayList.isEmpty())
{
String name = currentFile.getAbsolutePath().substring(baseName.length());
ZipEntry zipEntry = new ZipEntry(name + "/" + ".");
zipOutputStream.putNextEntry(zipEntry);
}
for (File file : filesArrayList)
{
if (file.isDirectory())
{
zipFilesInPath(zipOutputStream, file.getAbsolutePath(), baseName);
}
else
{
String name = file.getAbsolutePath().substring(baseName.length());
ZipEntry zipEntry = new ZipEntry(name);
zipOutputStream.putNextEntry(zipEntry);
IOUtils.copy(new FileInputStream(file), zipOutputStream);
zipOutputStream.closeEntry();
}
}
}
private static void unzipFilesToPath(ZipInputStream zipInputStream, String fileExtractPath) throws IOException
{
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null)
{
int count;
byte[] data = new byte[2048];
/*let's make the directory structure needed*/
File destFile = new File(fileExtractPath, entry.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory() && !entry.getName().substring(entry.getName().length() - 1).equals("."))
{
final FileOutputStream fos = new FileOutputStream(fileExtractPath + File.separator + entry.getName());
final BufferedOutputStream dest = new BufferedOutputStream(fos, 2048);
while ((count = zipInputStream.read(data, 0, 2048)) != -1)
{
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
}
}
apparently is not possible, and what you have to do is package all your files into a tar/zip and then apply the lzma. take a look at this How to use LZMA SDK to compress/decompress in Java
I am using jtar-1.1 to try extract files from a tar file, im using the following code to try extract the files
String tarFile = "c:/test/test.tar";
String destFolder = "c:/test/myfiles";
// Create a TarInputStream
TarInputStream tis = new TarInputStream(new BufferedInputStream(new FileInputStream(tarFile)));
while (( entry = tis.getNextEntry() ) != null) {
System.out.println( "Extracting: " + entry.getName() );
int count;
byte data[] = new byte[BUFFER];
if (entry.isDirectory()) {
new File( destFolder + "/" + entry.getName() ).mkdirs();
continue;
} else {
int di = entry.getName().lastIndexOf( '/' );
if (di != -1) {
new File( destFolder + "/" + entry.getName().substring( 0, di ) ).mkdirs();
}
}
FileOutputStream fos = new FileOutputStream( destFolder + "/" + entry.getName() );
BufferedOutputStream dest = new BufferedOutputStream( fos );
while (( count = tis.read( data ) ) != -1) {
dest.write( data, 0, count );
}
dest.flush();
dest.close();
}
}
EDIT:
I have edited the code above to check is the entry a directory and once i done this it got rid of the FileNotFound error... the above code now works
I think you need to create the path before opening the FileOutputStream.
Similar Thread Here
Just off the cuff, perhaps the issue is that the entry you are receiving contains a subfolder that hasn't been created yet: 'LAB3'? In this case the directory 'LAB3' doesn't exist in the file system because you haven't created it and the file 'sg5' intends to be placed there so when you try to create a file on the fully qualified path that includes LAB3 it complains.
NOTE: This is a followup to my question here.
I have a program that takes the contents of a directory and bundles everything into a JAR file. The code I use to do this is here:
try
{
FileOutputStream stream = new FileOutputStream(target);
JarOutputStream jOS = new JarOutputStream(stream);
LinkedList<File> fileList = new LinkedList<File>();
buildList(directory, fileList);
JarEntry jarAdd;
String basePath = directory.getAbsolutePath();
byte[] buffer = new byte[4096];
for(File file : fileList)
{
String path = file.getPath().substring(basePath.length() + 1);
path.replaceAll("\\\\", "/");
jarAdd = new JarEntry(path);
jarAdd.setTime(file.lastModified());
jOS.putNextEntry(jarAdd);
FileInputStream in = new FileInputStream(file);
while(true)
{
int nRead = in.read(buffer, 0, buffer.length);
if(nRead <= 0)
break;
jOS.write(buffer, 0, nRead);
}
in.close();
}
jOS.close();
stream.close();
So, all is well and good and the jar gets created, and when I explore its contents with 7-zip it has all the files I need. However, when I try to access the contents of the Jar via a URLClassLoader (the jar is not on the classpath and I don't intend it to be), I get null pointer exceptions.
The odd thing is, when I use a Jar that I've exported from Eclipse, I can access the contents of it in the way I want. This leads me to believe that I'm somehow not creating the Jar correctly, and am leaving something out. Is there anything missing from the method up above?
I figured it out based on this question - the problem was me not properly handling backslashes.
Fixed code is here:
FileOutputStream stream = new FileOutputStream(target);
JarOutputStream jOS = new JarOutputStream(stream);
LinkedList<File> fileList = new LinkedList<File>();
buildList(directory, fileList);
JarEntry entry;
String basePath = directory.getAbsolutePath();
byte[] buffer = new byte[4096];
for(File file : fileList)
{
String path = file.getPath().substring(basePath.length() + 1);
path = path.replace("\\", "/");
entry = new JarEntry(path);
entry.setTime(file.lastModified());
jOS.putNextEntry(entry);
FileInputStream in = new FileInputStream(file);
while(true)
{
int nRead = in.read(buffer, 0, buffer.length);
if(nRead <= 0)
break;
jOS.write(buffer, 0, nRead);
}
in.close();
jOS.closeEntry();
}
jOS.close();
stream.close();
I'm using this script on WINDOWS
public void copyFile(File sourceDirectory, File targetFile, File targetDirectory) throws IOException{
String temp = targetFile.getAbsolutePath();
String relativeD = temp.substring(sourceDirectory.getAbsolutePath().length(), targetFile.getAbsolutePath().length());
String rootD = sourceDirectory.getName();
String fullPath = targetDirectory.getAbsolutePath() + rootD + relativeD;
File fP = new File( fullPath );
System.out.println("PATH: " + fullPath);
FileChannel inChannel = new FileInputStream(targetFile).getChannel();
FileChannel outChannel = new FileOutputStream( fP ).getChannel();
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = inChannel.size();
long position = 0;
while (position < size) {
position += inChannel.transferTo(position, maxCount, outChannel);
}
if (inChannel != null) inChannel.close();
if (outChannel != null) outChannel.close();
}
What I'm doing is simple. I need to copy a file from a location to another but I have to keep the directories they're in.
So with relativeD I'm taking something like this: dir/files.sql or simply files.sql.
This is happening because for specific directories I need to copy them recursively respecting the tree structure.
The problem is this method is not working. I don't know why because if I use a simple
FileChannel outChannel = new FileOutputStream( new File( targetDirectory, targetFile ) ).getChannel();
it works. I suppose this is happening because in this case it's copying the file under an existing directory.
According to this article (top Google search hit for 'java mkdir recursive'):
Have a look at the java.io.File : it does the job perfectly, with the mkdirs function :
new File("c:/aaa/bbb/ccc/ddd").mkdirs();