I create a zip file using below code. Zip is created properly, then later in my program I try to get a zip entry from this file. And if I print a zip entry name I get windows path separators(Eg \a\b\c). But I need this like a/b/c. I have not posted reading zip entry code.
public static void zipFolder(File subdirs, String ZipName) throws FileNotFoundException, IOException {
try (FileOutputStream fileWriter = new FileOutputStream(location+File.seperator+ ZipName);
ZipOutputStream zip = new ZipOutputStream(fileWriter)) {
addFolderToZip(subdirs, subdirs, zip);
}
}
private static void addFileToZip(File rootPath, File srcFile, ZipOutputStream zip) throws FileNotFoundException, IOException {
if (srcFile.isDirectory()) {
addFolderToZip(rootPath, srcFile, zip);
} else {
byte[] buf = new byte[1024];
int len;
try (FileInputStream in = new FileInputStream(srcFile)) {
String name = srcFile.getPath();
name = name.replace(rootPath.getPath() + File.separator, "");
zip.putNextEntry(new ZipEntry(name));
while ((len = in.read(buf)) > 0) {
zip.write(buf, 0, len);
}
}
}
}
private static void addFolderToZip(File rootPath, File srcFolder, ZipOutputStream zip) throws FileNotFoundException, IOException {
for (File fileName : srcFolder.listFiles()) {
addFileToZip(rootPath, fileName, zip);
}
}
The root cause of your problem in the following snippet:
String name = srcFile.getPath();
name = name.replace(rootPath.getPath() + File.separator, "");
zip.putNextEntry(new ZipEntry(name));
The File.getPath() method returns the path with the system-dependent default name-separator.
So, according to this
Within a ZIP file, pathnames use the forward slash / as separator, as required by the ZIP spec (4.4.17.1). This requires a conversion from or to the local file.separator on systems like Windows. The API (ZipEntry) does not take care of the transformation, and the need for the programmer to deal with it is not documented.
you should rewrite this snippet in the following way:
String name = srcFile.getPath();
name = name.replace(rootPath.getPath() + File.separator, "");
if (File.separatorChar != '/') {
name = name.replace('\\', '/');
}
zip.putNextEntry(new ZipEntry(name));
Related
I need to extract tar file by this code.
But it' this error when I use FileOutputStream(outputFile);
" java.io.FileNotFoundException: D:\TestFile\1.png (Access is denied)"
Input is 1.tar file from Drive D:/testFile
and extract to same folder
I try check path of outputfile by outputFile.getCanonicalFile but it's ok!!
what wrong?
public class DecompressTarFile {
public ArrayList<File> getTarFileExtracted() {
return tarFileExtracted;
}
public ArrayList<File> tarFileExtracted = new ArrayList<File>();
public DecompressTarFile(File inputFile, File outputDir) throws FileNotFoundException, ArchiveException, IOException {
System.out.println("Untaring " + inputFile.getAbsolutePath() + " to dir " + outputDir.getAbsolutePath() + ".");
InputStream inputStream = new FileInputStream(inputFile);
TarArchiveInputStream tarStream = (TarArchiveInputStream) new ArchiveStreamFactory().createArchiveInputStream("tar", inputStream);
TarArchiveEntry tarEntry = null;
while ((tarEntry = (TarArchiveEntry) tarStream.getNextEntry()) != null) {
File outputFile = new File(outputDir, tarEntry.getName());
System.out.println("Attempting to write output directory " + outputFile.getAbsolutePath());
if (!outputFile.exists()) {
System.out.println("Attempting to create output directory " + outputFile.getAbsolutePath());
if (!outputFile.mkdirs()) {
throw new IllegalStateException(String.format("Couldn't create directory %s.", outputFile.getAbsolutePath()));
}
} else {
System.out.println("Create output file " + outputFile.getAbsolutePath());
OutputStream outputFileStream = new FileOutputStream(outputFile);
IOUtils.copy(tarStream, outputFileStream);
outputFileStream.close();
}
tarFileExtracted.add(outputFile);
}
tarStream.close();
}
}
and called by main class
static File tarFileInput = new File("D:/TestFile/haha.tar");
static File tarPathFileOutput = new File("D:/TestFile");
public static void main(String[] args) throws ArchiveException, IOException {
decomp = new DecompressTarFile(tarFileInput, tarPathFileOutput);
//listOutput = decomp.getTarFileExtracted();
}
And this result from this code
run:
Untaring D:\TestFile\haha.tar to dir D:\TestFile.
Attempting to write output directory D:\TestFile\1.png
Create output file D:\TestFile\1.png
Exception in thread "main" java.io.FileNotFoundException: D:\TestFile\1.png (Access is denied)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
at java.io.FileOutputStream.<init>(FileOutputStream.java:171)
at com.service..TarFile.DecompressTarFile.<init>(DecompressTarFile.java:53)
at com.service..TarFile.MainForTest.main(MainForTest.java:28)
Java Result: 1
This is the problem:
Attempting to write output directory D:\TestFile\1.png
You've created the target filename as a directory. You need to separate out "the directory I need to exist" and "the file I want to write to". For example:
File outputFile = new File(outputDir, tarEntry.getName());
File outputDirectory = outputFile.getParent();
if (!outputDirectory.exists()) {
// Try to create the directory
}
Oh, and also you've got a loop condition of:
while (tarEntry != null)
... but you're not changing the value of tarEntry in the loop...
I am creating a zip file and downloading it. I am able to download all file files with out any error. But the files in the zip are placing in nested folders according to the files real path like C>Users>workspace>.metadata>.plugins>org.eclipse.wst.server.core>tmp0>wtpwebapps>finaldebrief while I am trying to zip 'finaldebrief' folder only. I want to get 'finaldebrief' folder directly in zip file. can someone help me out. Thanks in Advance.
Here is my code
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int workshopid = Integer.parseInt(request.getParameter("currentworkshopid"));
javax.servlet.ServletContext context = getServletConfig().getServletContext();
String path = context.getRealPath("finaldebrief");
try
{
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=finaldebrief.zip");
ZipOutputStream zos = new
ZipOutputStream(response.getOutputStream());
zipDir(path + "/", zos);
zos.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void zipDir(String dir2zip, ZipOutputStream zos)
{
try
{
//create a new File object based on the directory we have to zip File
File zipDir = new File(dir2zip);
//get a listing of the directory content
String[] dirList = zipDir.list();
byte[] readBuffer = new byte[2156];
int bytesIn = 0;
//loop through dirList, and zip the files
for(int i=0; i<dirList.length; i++)
{
File f = new File(zipDir, dirList[i]);
if(f.isDirectory())
{
//if the File object is a directory, call this
//function again to add its content recursively
String filePath = f.getPath();
// String filePath = f.getCanonicalPath();
zipDir(filePath, zos);
//loop again
continue;
}
//if we reached here, the File object f was not a directory
//create a FileInputStream on top of f
FileInputStream fis = new FileInputStream(f);
// create a new zip entry
ZipEntry anEntry = new ZipEntry(f.getPath());
//place the zip entry in the ZipOutputStream object
zos.putNextEntry(anEntry);
//now write the content of the file to the ZipOutputStream
while((bytesIn = fis.read(readBuffer)) != -1)
{
zos.write(readBuffer, 0, bytesIn);
}
//close the Stream
fis.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
Within the line
ZipEntry anEntry = new ZipEntry(f.getPath());
you specify the path inside your zip file (i.e. f.getPath()). If you want a shorter path or none at all just manipulate this part (e.g. f.getName()).
I want to download entire folder/directory from server.
The folder contain files. I tried it with zip functionality but for that i need to give path till the files and not the folder path.
like -
BufferedInputStream in = new BufferedInputStream(new FileInputStream("d:\\StoreFiles\\Temp\\profile.txt"));
I want something like ("d:\StoreFiles") which will download all the folders in Storefiles folder and the files inside the folder.
How can i implement this?
How about this? It recursively going in the directory and downloading:
public static void main(String[] args) {
directoryDownloader(new File("/Users/eugene/Desktop"));
}
private static void directoryDownloader(File input){
if(input.isDirectory()){
for(File file : input.listFiles()){
directoryDownloader(file);
}
} else {
downloadFile(input);
}
}
private static void downloadFile(File someFile){
System.out.println("Downloading file : " + someFile.getPath());
}
P.S. Implement the downloadFile how you want.
I would suggest looking at Apache Commons IO FileUtils to copy directories. It's pretty easy to use. Have a look at the javadoc
Some of the useful methods that might come in handy (note that there are several ones available):
copyDirectory(File srcDir, File destDir)
copyDirectory(File srcDir, File destDir, FileFilter filter)
I think this example useful for u
public class CopyDirectoryExample
{
public static void main(String[] args)
{
File srcFolder = new File("c:\\mkyong");
File destFolder = new File("c:\\mkyong-new");
//make sure source exists
if(!srcFolder.exists()){
System.out.println("Directory does not exist.");
//just exit
System.exit(0);
}else{
try{
copyFolder(srcFolder,destFolder);
}catch(IOException e){
e.printStackTrace();
//error, just exit
System.exit(0);
}
}
System.out.println("Done");
}
public static void copyFolder(File src, File dest)
throws IOException{
if(src.isDirectory()){
//if directory not exists, create it
if(!dest.exists()){
dest.mkdir();
System.out.println("Directory copied from "
+ src + " to " + dest);
}
//list all the directory contents
String files[] = src.list();
for (String file : files) {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile,destFile);
}
}else{
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in.close();
out.close();
System.out.println("File copied from " + src + " to " + dest);
}
}
}
A proprietary program that I'm working with zips up and extracts certain files without changing the modified date of the files when unzipping. I'm also creating my own zip and extraction tool based off the source code in our program but when I'm unzipping the files the modified date of all zipped files is showing with the unzip time & date. Here's the code for my extraction:
public static int unzipFiles(File zipFile, File extractDir) throws Exception
{
int totalFileCount = 0;
String zipFilePath = zipFile.getPath();
System.out.println("Zip File Path: " + zipFilePath);
ZipFile zfile = new ZipFile(zipFile);
System.out.println("Size of ZipFile: "+zfile.size());
Enumeration<? extends ZipEntry> entries = zfile.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
System.out.println("ZipEntry File: " + entry.getName());
File file = new File(extractDir, entry.getName());
if (entry.isDirectory())
{
System.out.println("Creating Directory");
file.mkdirs();
}
else
{
file.getParentFile().mkdirs();
InputStream in = zfile.getInputStream(entry);
try
{
copy(in, file);
}
finally
{
in.close();
}
}
totalFileCount++;
}
return totalFileCount;
}
private static void copy(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
System.out.println("InputStream/OutputStram copy");
while (true)
{
int readCount = in.read(buffer);
if (readCount < 0)
{
break;
}
out.write(buffer, 0, readCount);
}
}
I'm sure there is a better way to do this other than doing the inputstream/outputstream copy. I'm sure this is the culprit as doing an extraction with winRAR does not change the date with the files I zipped.
Use ZipEntry.getTime to get the last-modified time and File.setLastModified to set it on the file after you are done copying it.
Is there an easy way to recursively ZIP a directory that may or may not contain any number of files and any number of levels of subdirectories?
public final class ZipFileUtil {
public static void zipDirectory(File dir, File zipFile) throws IOException {
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);
zipSubDirectory("", dir, zout);
zout.close();
}
private static void zipSubDirectory(String basePath, File dir, ZipOutputStream zout) throws IOException {
byte[] buffer = new byte[4096];
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
String path = basePath + file.getName() + "/";
zout.putNextEntry(new ZipEntry(path));
zipSubDirectory(path, file, zout);
zout.closeEntry();
} else {
FileInputStream fin = new FileInputStream(file);
zout.putNextEntry(new ZipEntry(basePath + file.getName()));
int length;
while ((length = fin.read(buffer)) > 0) {
zout.write(buffer, 0, length);
}
zout.closeEntry();
fin.close();
}
}
}
}
You can use the Java API Specification
and How do you recursively traverse through file folders?.
I use the ZipFileSystem implementation in ruby with great success, though I've never used it in java. You might want to check this out: