I am trying to implement a function that un-tars a file. Below is the code I have written using JTar
private void untar(String tarFile, String destFolder) throws IOException {
TarInputStream tis = new TarInputStream(new BufferedInputStream(new FileInputStream(tarFile)));
TarEntry entry;
while (( entry = tis.getNextEntry() ) != null) {
System.out.println( "Extracting: " + entry.getName() );
int count;
byte data[] = new byte[2048];
if (entry.isDirectory()) {
new File( destFolder + "/" + entry.getName() ).mkdirs();
continue;
} else {
int di = entry.getName().lastIndexOf( '/' );
System.out.println("File"+di);
if (di != -1) {
File f = new File( destFolder + "/" + entry.getName().substring( 0, di ) );
if(f.mkdirs())
System.out.println(f.isDirectory());
}
}
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();
}
tis.close();
}
When I hit the mkdirs() part and try to create a directory it does not do so, and I cannot see any output on console after the if statement.
Possibly this is the reason that the subsequent code for FileOutputStream shows an IOexception stating not a directory.
I can't find a solution for this problem anywhere.
Related
I've created a pretty simple Java GUI to browse/load a zip file on Windows platform to begin unzipping and then do some file checking.
Everything works fine except that I have to close the GUI window in order to delete the zip file that has been opened in the GUI.In my finally block of the unzipping method, I've tried adding the following:
public static String unZip(String path)
{
int count = -1;
String savepath = "";
File file = null;
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
savepath = path.substring(0, path.lastIndexOf("\\")) + File.separator; //File saving directory
new File(savepath).mkdir(); //create the saving directory
ZipFile zipFile = null;
String topLevelDirName="";
try
{
zipFile = new ZipFile(path,Charset.forName("gbk")); //Encoding
Enumeration<?> entries = zipFile.entries();
int levelCount=0;
while(entries.hasMoreElements())
{
byte buf[] = new byte[buffer];
ZipEntry entry = (ZipEntry)entries.nextElement();
String filename = entry.getName();
boolean ismkdir = false;
if(filename.lastIndexOf("/") != -1){ //To check if there is a directory
ismkdir = true;
}
filename = savepath + filename;
if(entry.isDirectory()){ //If it is a directory
levelCount++;
file = new File(filename);
file.mkdirs();
if(levelCount==1)
topLevelDirName = filename;
continue;
}
file = new File(filename);
if(!file.exists()){
if(ismkdir){
new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs();
}
}
file.createNewFile(); //Create the file
is = zipFile.getInputStream(entry);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, buffer);
while((count = is.read(buf)) > -1)
{
bos.write(buf, 0, count);
}
bos.flush();
bos.close();
fos.close();
is.close();
}
zipFile.close();
}catch(IOException ioe){
ioe.printStackTrace();
}finally{
try{
if(bos != null){
bos.close();
}
if(fos != null) {
fos.close();
}
if(is != null){
is.close();
}
if(zipFile != null){
zipFile.close();
}
}catch(Exception e) {
e.printStackTrace();
}
return topLevelDirName;
}
}
However, I am still not able to delete the zip unless explicitly close the GUI.
Wonder if there is anything to do with the Windows file handle?Thanks in advance.
Java 8 introduced the try-with-resources Statement to make this kind of situation simpler and cleaner.
One of the issues you have is, if any one of the attempts to close the many resources you have open fails, then none of the others will be closed
public static String unZip(String path) throws IOException {
int count = -1;
File sourceFile = new File(path);
String name = sourceFile.getName();
name = name.substring(0, name.lastIndexOf(".zip"));
File sourcePath = new File(sourceFile.getParent(), name);
System.out.println("SavePath = " + sourcePath);
if (!sourcePath.exists() && !sourcePath.mkdirs()) {
throw new IOException("Could not create directory " + sourcePath);
}
String topLevelDirName = "";
try (ZipFile zipFile = new ZipFile(sourceFile)) {
Enumeration<?> entries = zipFile.entries();
int levelCount = 0;
byte buf[] = new byte[1024];
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String filename = entry.getName();
File file = new File(sourcePath, filename);
if (entry.isDirectory()) { //If it is a directory
levelCount++;
System.out.println("Make directory " + file);
if (!file.exists() && !file.mkdirs()) {
throw new IOException("Could not create directory " + filename);
}
} else {
System.out.println("Extract to " + file);
try (InputStream is = zipFile.getInputStream(entry);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
while ((count = is.read(buf)) > -1) {
bos.write(buf, 0, count);
}
}
}
}
}
return topLevelDirName;
}
I've update the code slightly to try and make it a little cleaner and simpler and to take advantage of the available APIs
I am trying to zip '.jpg' files stored in external storage so that I can send that .zip file to server. Here's a snippet of the code. So far, the zip folder is created but there are no files inside. And while opening the zip using winrar, i get "Unexpected end of archive" message.
String[] s = new String[10];
ZipManager zipManager = new ZipManager();
File f = new File(inputPath + _report + "/");
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
String filePath = file.getPath();
if (filePath.endsWith(".jpg")) {
tFilelist.add(filePath.substring(63, 98));
s[a] = inputPath + _report + "/" + tFilelist.get(a);
a++;
}
}
zipManager.zip(s, inputPath + _report + inputFile);
Here's ZipManager class :
public class ZipManager {
private static final int BUFFER = 80000;
public void zip(String[] _files, String zipFileName) {
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(zipFileName);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
byte data[] = new byte[BUFFER];
for (int i = 0; i < _files.length; i++) {
Log.v("Compress", "Adding: " + _files[i]);
FileInputStream fi = new FileInputStream(_files[i]);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(_files[i].substring(_files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void dirChecker(String dir) {
File f = new File(dir);
if (!f.isDirectory()) {
f.mkdirs();
}
}
}
You have to close your file entries. Use out.closeEntry(); after writing the content.
for (int i = 0; i < _files.length; i++) {
Log.v("Compress", "Adding: " + _files[i]);
FileInputStream fi = new FileInputStream(_files[i]);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(_files[i].substring(_files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry); // open your file entry
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
out.closeEntry(); // close your file entry
origin.close();
}
I have this updater class that updates my program by unzipping a zip file. It works good except when I add in a folder for it to extract.. I have included the 3 methods that I use to accomplish this but the problem must lie in the unzip() method.
Once it prints Extracting: New folder/TEST2.txt it makes the error posted below. I have tried making the folder without spaces and it throws the same error. The contests of the zip file are just 2 text files and a folder.
Structure of zip:
New Folder >Test2.txt
Test1.txt
Errors:
java.io.IOException: The system cannot find the path specified at
java.io.WinNTFileSystem.createFileExclusively(Native Method) at
java.io.File.createNewFile(Unknown Source) at
update.Main_Gui.unzip(Main_Gui.java:244) at
update.Main_Gui.access$3(Main_Gui.java:230) at
update.Main_Gui$3.run(Main_Gui.java:108) at
java.lang.Thread.run(Unknown Source)
Code:
private void copyFiles(File f, String dir) throws IOException {
File[] files = f.listFiles();
for (File ff : files) {
if (ff.isDirectory()) {
new File(dir + "/" + ff.getName()).mkdir();
copyFiles(ff, dir + "/" + ff.getName());
} else {
copy(ff.getAbsolutePath(), dir + "/" + ff.getName());
}
}
}
public void copy(String srFile, String dtFile)
throws FileNotFoundException, IOException {
File f1 = new File(srFile);
File f2 = new File(dtFile);
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
private void unzip() throws IOException {
int BUFFER = 2048;
BufferedOutputStream dest = null;
BufferedInputStream is = null;
ZipEntry entry;
ZipFile zipfile = new ZipFile("update.zip");
Enumeration e = zipfile.entries();
(new File(root)).mkdir();
while (e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
outText.setText(outText.getText() + "\nExtracting: " + entry);
if (entry.isDirectory())
(new File(root + entry.getName())).mkdir();
else {
(new File(root + entry.getName())).createNewFile();
is = new BufferedInputStream(zipfile.getInputStream(entry));
int count;
byte data[] = new byte[BUFFER];
FileOutputStream fos = new FileOutputStream(root
+ entry.getName());
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
//zipfile.close();
dest.flush();
dest.close();
is.close();
}
}
}
I have function like this in my Bean:
public String uploadFile(UploadedFile uploadedFile) {
logger.info("Enter: uploadFile(UploadedFile uploadedFile).");
String name = uploadedFile.getName();
String extension = name.substring(name.length() - 3);
if (extension.contentEquals("peg")) {
extension = "jpeg";
}
RandomString rs = new RandomString(RANDOM_PHOTO_NAME_LENGTH);
this.randomPhotoName = rs.nextString();
String fileName = this.randomPhotoName + "." + extension;
logger.info("File name: " + name + ". Extension: " + extension + ". New fileName: " + fileName);
ServletContext sc = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
File f = new File(
sc.getRealPath(Constant.USER_FILE_PATH));
if (!f.exists()) {
logger.info("Folder "
+ Constant.USER_FILE_PATH
+ " nie istniej. Tworze nowy.");
f.mkdirs();
}
File backupFile = new File(
sc.getRealPath(Constant.USER_FILE_PATH
+ fileName));
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(uploadedFile.getInputStream());
out = new FileOutputStream(backupFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
} catch (IOException ioe) {
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage msg = null;
msg = new FacesMessage(
"Pojawił się nieoczekiwany błąd przy uploadowaniu pliku.");
context.addMessage(null, msg);
logger.error(
"Pojawił się nieoczekiwany błąd przy uploadowaniu pliku.",
ioe);
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
logger.info("Exit: uploadFile(UploadedFile uploadedFile).");
return fileName;
}
And all files are saved in tmp directory eg:
\jboss-5.1.0.GA\server\default\tmp\a006-czo4uq-gzzu4l42-1-gzzuk7xr-a2\TupTus.war\media\img\user-gallery\6u2fpgu3tkzniwg.JPG
Because all your files are built as:
File backupFile = new File(
sc.getRealPath(Constant.USER_FILE_PATH
+ fileName));
Sounds like sc.getRealPath() returns working directory that JBoss allocates for your application.
So, the real question is to you: where do you want to write the files? If not there, so where? If you prefer user temporary directory use new File(System.getProperty("java.io.tmpdir"), fileName) and write there.
If you want to be able to configure the path out of the box you can store this path either in DB or configuration file or pass it via your custom system properties when you are running JBoss using command line switch -D.
IMO, I thought that epub is a kind of zip . Thus, I've tried to unzip in a way.
public class Main {
public static void main(String argv[ ]) {
final int BUFFER = 2048;
try {
BufferedOutputStream dest = null;
FileInputStream fis = new FileInputStream("/Users/yelinaung/Documents/unzip/epub/doyle.epub");
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
System.out.println("Extracting: " + entry);
int count;
byte data[] = new byte[BUFFER];
// write the files to the disk
FileOutputStream fos = new FileOutputStream("/Users/yelinaung/Documents/unzip/xml/");
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER))
!= -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
} catch ( IOException e) {
e.printStackTrace();
}
}
}
I got that following error ..
java.io.FileNotFoundException: /Users/yelinaung/Documents/unzip/xml (No such file or directory)
though I've created a folder in that way .. and
my way of unzipping epub is right way ? .. Correct Me
I've got the answer.. I haven't checked that the object that have to be extracted is folder or not .
I've corrected in this way .
public static void main(String[] args) throws IOException {
ZipFile zipFile = new ZipFile("/Users/yelinaung/Desktop/unzip/epub/doyle.epub");
String path = "/Users/yelinaung/Desktop/unzip/xml/";
Enumeration files = zipFile.entries();
while (files.hasMoreElements()) {
ZipEntry entry = (ZipEntry) files.nextElement();
if (entry.isDirectory()) {
File file = new File(path + entry.getName());
file.mkdir();
System.out.println("Create dir " + entry.getName());
} else {
File f = new File(path + entry.getName());
FileOutputStream fos = new FileOutputStream(f);
InputStream is = zipFile.getInputStream(entry);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = is.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
fos.close();
System.out.println("Create File " + entry.getName());
}
}
}
Then, got it .
You are creating a FileOutputStream with the same name for every file inside your epub file.
The FileNotFoundException is thrown if the file exists and it is a directory. The first time you pass through the loop, the directory is created and in the next time, the exception is raised.
If you want to change the directory where the epub is extracted, you should do something like this:
FileOutputStream fos = new FileOutputStream("/Users/yelinaung/Documents/unzip/xml/" + entry.getName())
Update
Creating the folder before to extract each file I was able to open the epub file
...
byte data[] = new byte[BUFFER];
String path = entry.getName();
if (path.lastIndexOf('/') != -1) {
File d = new File(path.substring(0, path.lastIndexOf('/')));
d.mkdirs();
}
// write the files to the disk
FileOutputStream fos = new FileOutputStream(path);
...
And to change the folder where the files are extracted, just change the line where the path is defined
String path = "newFolder/" + entry.getName();
This method worked fine for me,
public void doUnzip(String inputZip, String destinationDirectory)
throws IOException {
int BUFFER = 2048;
List zipFiles = new ArrayList();
File sourceZipFile = new File(inputZip);
File unzipDestinationDirectory = new File(destinationDirectory);
unzipDestinationDirectory.mkdir();
ZipFile zipFile;
// Open Zip file for reading
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
// Create an enumeration of the entries in the zip file
Enumeration zipFileEntries = zipFile.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(unzipDestinationDirectory, currentEntry);
if (currentEntry.endsWith(".zip")) {
zipFiles.add(destFile.getAbsolutePath());
}
// grab file's parent directory structure
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
try {
// extract file if not a directory
if (!entry.isDirectory()) {
BufferedInputStream is =
new BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest =
new BufferedOutputStream(fos, BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
zipFile.close();
for (Iterator iter = zipFiles.iterator(); iter.hasNext();) {
String zipName = (String)iter.next();
doUnzip(
zipName,
destinationDirectory +
File.separatorChar +
zipName.substring(0,zipName.lastIndexOf(".zip"))
);
}
}