I do have a Folder in my Ressources i want to extract to disk when the App is started the first time. I do have this peace of code here where I tried to copy them to disk, but all I get are empty files. The folder contains .gnh files. Where am I loosing my Bytes of the File?
public void getTemplates() throws URISyntaxException {
final URL url = TemplateUtils.class.getResource("/templates/");
if (url != null) {
final File dir = new File(url.toURI());
for (final File file : dir.listFiles()) {
try {
final OutputStream outStream = new FileOutputStream(
PathManager.INSTANCE.getRootPath() + file.getName());
final long writtenBytes = Files.copy(file.toPath(), outStream);
LOG.info(writtenBytes);
outStream.flush();
outStream.close();
} catch (final IOException e) {
LOG.error(e.getMessage(), e);
}
}
}
}
the LOG.info(writtenBytes) says 0
EDIT:
When I copy simple text Files everything is working fine. But with those .gnh Files nothing is working anymore. Is there another way to extract those Files to disk?
I got the solution: You need to create the File for the OutputStream first and then you can flush it.
final File path = new File(
PathManager.INSTANCE.getRootPath() + "templates");
path.mkdirs();
final File newFile = new File(path.toString()
+ File.separator + file.getName());
newFile.createNewFile();
final OutputStream outStream = new FileOutputStream(newFile);
Files.copy(file.toPath(), outStream);
outStream.flush();
outStream.close();
Related
I am trying to generate a zip file in Java, that contains several files of different types (e.g. images, fonts etc) that are lying in different locations. Furthermore I want the zip file to have subfolders where the files are put by their type (e.g. images should go to the images folder within the zip.
These are the files that I have (each can be in a different location):
index.html
img1.jpg
img2.jpg
font1.woff
font2.woff
style.css
custom.js
And this is how they should be in the zip file:
index.html
images/img1.jpg
images/img2.jpg
fonts/font1.woff
fonts/font2.woff
js/custom.js
css/styles.css
So far I have managed to take one file in a specific path and prompt the user for the output location. A zip-file will be generated with the file that is specified in the input. Here is the code I have so far:
JFrame parentFrame = new JFrame();
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Speicherort auswählen");
int userSelection = fileChooser.showSaveDialog(parentFrame);
String pathToFile;
if (userSelection == JFileChooser.APPROVE_OPTION) {
File fileToSave = fileChooser.getSelectedFile();
print(fileToSave.getAbsolutePath());
pathToFile = fileToSave.getAbsolutePath();
}
pathToFile = pathToFile.replace("\\", "/");
String outFileName = pathToFile;
String inFileName = "C:/Users/asoares/Desktop/mobio_export_test/index.html";
ZipOutputStream zos = null;
FileInputStream fis = null;
try {
zos = new ZipOutputStream(new FileOutputStream(outFileName));
fis = new FileInputStream(inFileName);
zos.putNextEntry(new ZipEntry(new File(inFileName).getName()));
int len;
byte[] buffer = new byte[2048];
while((len = fis.read(buffer, 0, buffer.length)) > 0) {
zos.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {}
}
if(zos != null){
try {
zos.closeEntry();
zos.close();
} catch (IOException e) {}
}
}
I would be really glad if someone can help me!!!
It should work like this.
The zip directory name should at best be created by another method (there are more image types than jpg :)).
public static Path zip(List<Path> files, Path zipFileTarget) throws IOException {
try (FileOutputStream fos = new FileOutputStream(zipFileTarget.toFile());
ZipOutputStream zos = new ZipOutputStream(fos)) {
if (!Files.exists(zipFileTarget))
Files.createFile(zipFileTarget);
createEntries(files, zos);
zos.close();
return zipFileTarget;
}
}
private static List<String> createEntries(List<Path> files, ZipOutputStream zos) throws IOException {
List<String> zippedFiles = new ArrayList<>();
Matcher matcherFileExt = Pattern.compile("^.*\\.([^.]+)$").matcher("");
for (Path f : files) {
if (Files.isRegularFile(f)) {
String fileName = f.getFileName().toString();
String fileExt = matcherFileExt.reset(fileName).matches()
? matcherFileExt.replaceAll("$1")
: "unknown";
// You should determine the dir name with a more sophisticated
// approach.
String dir;
if (fileExt.equals("jpg")) dir = "images";
else if (fileExt.equals("woff")) dir = "fonts";
else dir = fileExt;
zos.putNextEntry(new ZipEntry(dir + "/" + fileName));
Files.copy(f, zos);
zippedFiles.add(fileName);
}
}
return zippedFiles;
}
Edit: this approach works with java 1.7+. You can easily convert a File object to a Path object by calling its toPath() method.
I have two jar files. Normally if I want to 'unpack' resource from my jar file I go for :
InputStream in = MyClass.class.getClassLoader().getResourceAsStream(name);
byte[] buffer = new byte[1024];
int read = -1;
File temp2 = new File(new File(System.getProperty("user.dir")), name);
FileOutputStream fos2 = new FileOutputStream(temp2);
while((read = in.read(buffer)) != -1) {
fos2.write(buffer, 0, read);
}
fos2.close();
in.close();
What If I would have another JAR files in the same directory? Can I access the second JAR file resources in simillar way? This second JAR is not runned so don't have own class loader. Is the only way to unzip this second JAR file?
I've used the below mentioned code to do the same kind of operation. It uses JarFile class to do the same.
/**
* Copies a directory from a jar file to an external directory.
*/
public static void copyResourcesToDirectory(JarFile fromJar, String jarDir, String destDir)
throws IOException {
for (Enumeration<JarEntry> entries = fromJar.entries(); entries.hasMoreElements();) {
JarEntry entry = entries.nextElement();
if (entry.getName().startsWith(jarDir + "/") && !entry.isDirectory()) {
File dest = new File(destDir + "/" + entry.getName().substring(jarDir.length() + 1));
File parent = dest.getParentFile();
if (parent != null) {
parent.mkdirs();
}
FileOutputStream out = new FileOutputStream(dest);
InputStream in = fromJar.getInputStream(entry);
try {
byte[] buffer = new byte[8 * 1024];
int s = 0;
while ((s = in.read(buffer)) > 0) {
out.write(buffer, 0, s);
}
} catch (IOException e) {
throw new IOException("Could not copy asset from jar file", e);
} finally {
try {
in.close();
} catch (IOException ignored) {}
try {
out.close();
} catch (IOException ignored) {}
}
}
}
If the other Jar is in your regular classpath then you can simply access the resource in that jar in the exact same way. If the Jar is just an file that's not on your classpath you will have to instead open it and extract the file with the JarFile and related classes. Note that Jar files are just special types of Zip files, so you can also access a Jar file with the ZipFile related classes
You can use URLClassLoader.
URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL("path_to_file//myjar.jar")})
classLoader.loadClass("MyClass");//is requared
InputStream stream = classLoader.getResourceAsStream("myresource.properties");
Let me just start out by saying I created an account on here because I've been beating my head against a wall in order to try and figure this out, so here it goes.
Also, I have already seen this question here. Neither one of those answers have helped and I have tried both of them.
I need to create a word document with a simple table and data inside. I decided to create a sample document in which to get the xml that I need to create the document. I moved all the folders from the unzipped docx file into my assets folder. Once I realized I couldn't write to the assets folder, I wrote a method to copy all the files and folders over to an external storage location of the device and then write the document I created to the same location. From there Im trying to zip the files back up to a .docx file. This is where things arent working.
The actual docx file is created and I can move it to my computer through the DDMS but when I go to view it Word says its corrupt. Heres whats weird though, if I unzip it and then rezip it on my computer without making any changes what so ever it works perfectly. I have used a program (for mac) called DiffMerge to compare the sample unzipped docx file to the unzipped docx that I have created and it says they are exactly the same. So, I think it has something to do with the zipping process in Android.
I have also tried unzipping the sample docx file on my computer, moving all the files and folders over to my assets folder including the document.xml file and just try to zip it up without adding my own document.xml file and using the sample one and that doesnt work either. Another thing I tried was to place the actual docx file in my assets folder, unzipping it onto my external storage and then rezipping it without doing anything. This also fails.
I'm basically at a loss. Please somebody help me figure this out.
Here is some of my code:
moveDocxFoldersFromAssetsToExternalStorage() is called first.
After that is called all the files have been moved over.
Then, I create the document.xml file and place it in the word directory where it belongs
Everything is where it should be and I now try to create the zip file.
.
private boolean moveDocxFoldersFromAssetsToExternalStorage(){
File rootDir = new File(this.externalPath);
rootDir.mkdir();
copy("");
// This is to get around a glitch in Android which doesnt list files or folders
// with an underscore at the beginning of the name in the assets folder.
// This renames them once they are saved to the device.
// We need it to show up in the list in order to move them.
File relsDir = new File(this.externalPath + "/word/rels");
File renameDir = new File(this.externalPath + "/word/_rels");
relsDir.renameTo(renameDir);
relsDir = new File(this.externalPath + "/rels");
renameDir = new File(this.externalPath + "/_rels");
relsDir.renameTo(renameDir);
// This is to get around a glitch in Android which doesnt list hidden files.
// We need it to show up in the list in order to move it.
relsDir = new File(this.externalPath + "/_rels/rels.rename");
renameDir = new File(this.externalPath + "/_rels/.rels");
relsDir.renameTo(renameDir);
return true;
}
private void copy(String outFileRelativePath){
String files[] = null;
try {
files = this.mAssetManager.list(ASSETS_RELATIVE_PATH + outFileRelativePath);
} catch (IOException e) {
e.printStackTrace();
}
String assetFilePath = null;
for(String fileName : files){
if(!fileName.contains(".")){
String outFile = outFileRelativePath + java.io.File.separator + fileName;
copy(outFile);
} else {
File createFile = new File(this.externalPath + java.io.File.separator + outFileRelativePath);
createFile.mkdir();
File file = new File(createFile, fileName);
assetFilePath =
ASSETS_RELATIVE_PATH + outFileRelativePath + java.io.File.separator + fileName;
InputStream in = null;
OutputStream out = null;
try {
in = this.mAssetManager.open(assetFilePath);
out = new FileOutputStream(file);
copyFile(in, out);
in.close();
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
private void zipFolder(String srcFolder, String destZipFile) throws Exception{
FileOutputStream fileWriter = new FileOutputStream(destZipFile);
ZipOutputStream zip = new ZipOutputStream(fileWriter);
zip.setMethod(Deflater.DEFLATED);
zip.setLevel(ZipOutputStream.STORED);
addFolderToZip(this.externalPath, "", zip);
zip.finish();
zip.close();
}
private void addFolderToZip(String externalPath, String folder, ZipOutputStream zip){
File file = new File(externalPath);
String files[] = file.list();
for(String fileName : files){
try {
File currentFile = new File(externalPath, fileName);
if(currentFile.isDirectory()){
String outFile = externalPath + java.io.File.separator + fileName;
addFolderToZip(outFile, folder + java.io.File.separator + fileName, zip);
} else {
byte[] buffer = new byte[8000];
int len;
FileInputStream in = new FileInputStream(currentFile);
zip.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
while((len = in.read(buffer)) > 0){
zip.write(buffer, 0, len);
}
zip.closeEntry();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
EDIT
Here is the code I wrote in order to get it working correctly based on what #edi9999 said below. I created a separate class that Im going to expand and add to and probably clean up a bit but this is working code. It adds all the files in a directory to the zip file and recursively calls itself to add all the subfiles and folders.
private class Zip {
private ZipOutputStream mZipOutputStream;
private String pathToZipDestination;
private String pathToFilesToZip;
public Zip(String pathToZipDestination, String pathToFilesToZip) {
this.pathToZipDestination = pathToZipDestination;
this.pathToFilesToZip = pathToFilesToZip;
}
public void zipFiles() throws Exception{
FileOutputStream fileWriter = new FileOutputStream(pathToZipDestination);
this.mZipOutputStream = new ZipOutputStream(fileWriter);
this.mZipOutputStream.setMethod(Deflater.DEFLATED);
this.mZipOutputStream.setLevel(8);
AddFilesToZip("");
this.mZipOutputStream.finish();
this.mZipOutputStream.close();
}
private void AddFilesToZip(String folder){
File mFile = new File(pathToFilesToZip + java.io.File.separator + folder);
String mFiles[] = mFile.list();
for(String fileName : mFiles){
File currentFile;
if(folder != "")
currentFile = new File(pathToFilesToZip, folder + java.io.File.separator + fileName);
else
currentFile = new File(pathToFilesToZip, fileName);
if(currentFile.isDirectory()){
if(folder != "")
AddFilesToZip(folder + java.io.File.separator + currentFile.getName());
else
AddFilesToZip(currentFile.getName());
} else {
try{
byte[] buffer = new byte[8000];
int len;
FileInputStream in = new FileInputStream(currentFile);
if(folder != ""){
mZipOutputStream.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
} else {
mZipOutputStream.putNextEntry(new ZipEntry(fileName));
}
while((len = in.read(buffer)) > 0){
mZipOutputStream.write(buffer, 0, len);
}
mZipOutputStream.closeEntry();
in.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
I think I've got what's wrong.
When I opened your corrupted File, and opened it on winrar, I saw antislashes at the beginning of the folders, which is unusual:
When I rezip the file after unzipping it, the antislashes are not there anymore and the file opens in Word so I think it should be the issue.
I think the code is wrong here:
String outFile = externalPath + java.io.File.separator + fileName;
should be
if (externalPath=="")
String outFile = externalPath + fileName;
else
String outFile = externalPath + java.io.File.separator + fileName;
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()).
When I am trying to extract the zip file into a folder as per the below code, for one of the entry (A text File) getting an error as "Invalid entry size (expected 46284 but got 46285 bytes)" and my extraction is stopping abruptly. My zip file contains around 12 text files and 20 TIF files. It is encountering the problem for the text file and is not able to proceed further as it is coming into the Catch block.
I face this problem only in Production Server which is running on Unix and there is no problem with the other servers(Dev, Test, UAT).
We are getting the zip into the servers path through an external team who does the file transfer and then my code starts working to extract the zip file.
...
int BUFFER = 2048;
java.io.BufferedOutputStream dest = null;
String ZipExtractDir = "/y34/ToBeProcessed/";
java.io.File MyDirectory = new java.io.File(ZipExtractDir);
MyDirectory.mkdir();
ZipFilePath = "/y34/work_ZipResults/Test.zip";
// Creating fileinputstream for zip file
java.io.FileInputStream fis = new java.io.FileInputStream(ZipFilePath);
// Creating zipinputstream for using fileinputstream
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new java.io.BufferedInputStream(fis));
java.util.zip.ZipEntry entry;
while ((entry = zis.getNextEntry()) != null)
{
int count;
byte data[] = new byte[BUFFER];
java.io.File f = new java.io.File(ZipExtractDir + "/" + entry.getName());
// write the files to the directory created above
java.io.FileOutputStream fos = new java.io.FileOutputStream(ZipExtractDir + "/" + entry.getName());
dest = new java.io.BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1)
{
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
zis.closeEntry();
}
catch (Exception Ex)
{
System.Out.Println("Exception in \"ExtractZIPFiles\"---- " + Ex.getMessage());
}
I can't understand the problem you're meeting, but here is the method I use to unzip an archive:
public static void unzip(File zip, File extractTo) throws IOException {
ZipFile archive = new ZipFile(zip);
Enumeration<? extends ZipEntry> e = archive.entries();
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
File file = new File(extractTo, entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
InputStream in = archive.getInputStream(entry);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
IOUtils.copy(in, out);
in.close();
out.close();
}
}
}
Calling:
File zip = new File("/path/to/my/file.zip");
File extractTo = new File("/path/to/my/destination/folder");
unzip(zip, extractTo);
I never met any issue with the code above, so I hope that could help you.
Off the top of my head, I could think of these reasons:
There could be problem with the encoding of the text file.
The file needs to be read/transferred in "binary" mode.
There could be an issue with the line ending \n or \r\n
The file could simply be corrupt. Try opening the file with a zip utility.