My project has a few xml templates that were modified and added to a zip file. The problem was that the templates were all in a template folder but the expected format of the zip file was to have them straight in the root.
project hierarchy:
templates/blah.xml
expected zip file hierarchy:
blah.xml
Anyway of achieving that without moving the xml files into the root folder of the project?
Thanks
I had a brain melt down... By using different names for input and output
byte[] buf = new byte[1024];
try
{
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targetFile));
FileInputStream in = new FileInputStream("templates/blah.xml");
out.putNextEntry(new ZipEntry("blah.xml"));
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
out.close();
} catch (IOException e)
{
e.printStackTrace();
}
You can subclass ZipEntry and make it do whatever you want. However, you need to find out how the code is getting hold of the contents, and then modify that to get the correct resource.
Related
I am working on a Software which bundles and exports XML files as a zip. The compression method is "Deflate" (Code snipped included below).
These zip files are needed in another (older) Software, which is build up on "QT" (Code snipped also below).
The Problem is, that the zip files are not accepted in the second Software. If these zip files get rezipped manually, they work suddendly.
To find any differences in the generated zip and the Manual one, i plugged both into "powerArchiver" and saw they are exactly the same except for the "Method", which is "DFLT-X" on the workign zip and "DFLT-N" on the not working one (Note: working refers to the second Software import, both zip files can be extracted without Problems manually).
Any ideas how i can get the "DFLT-X" Method with Java utils libs?
I tried all settings and variants (.setLevel(), setMethod()) for "ZipOutputStream", "Deflater" and "DeflaterOutputStream" but i only got the "DFLT-N" Format.
The Explanation what these Formats are is not included in the powerArchiver Forums or else where. "DFLT-N" seems to refer to "Deflate, Normal" and the X variant for some higher compression, but not Deflate64.
Software 1, generating the zip:
final byte[] buffer = new byte[1024];
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
FileInputStream inputStream = null;
for (final String file : this.fileList) {
if (file.toString().contains(".xml")) {
final ZipEntry ze = new ZipEntry(File.separator + file);
zos.putNextEntry(ze);
try {
inputStream = new FileInputStream(sourceFolder + File.separator + file);
int len;
while ((len = inputStream.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
}
finally {
if (inputStream != null) {
inputStream.close();
}
}
}
}
zos.closeEntry();
}
catch (final IOException ex) {
ex.printStackTrace();
}
Software 2, reading the zip:
bool WfControlDataStorage::load(const QString& identifier, QByteArray& outZipFileContent) const
{
QFile dataFile(identifierToFilepath(identifier));
if(dataFile.open(QFile::ReadOnly)) {
outZipFileContent = dataFile.readAll();
dataFile.close();
return true;
}
return false;
}
#Holger Thank you for your Time, sounds like you did exactly what i did too.
Solution:
in my Project the zip Entry name had a leading "/" like "/someName". This was not visible in powerarchiver and also didnt hinder decompressing, but my recieving software had troubles resolving this name.
Repacking with powerarchiver removed that slash, so a bunch of undocumented behavior made my life hell.
In Terms of DFLT-X and DFLT-N, these are strange powerarchiver specific namings and i still cannot say how they determine the difference. But i can say, that deflate has no different "methods" nexto the simple levels from 0-9 and the "Deflate64" which is basically never used and obsolete. The DFLT-X naming is unrelated to both and imho completly irrelevant.
I have some word documents and excel sheets which has some images along with the file text content. I want to create a copy of that file and keep it at a specific location. I tried the following method which is creating file at specified location but the file is corrupted and cannot be read.
InputStream document = Thread.currentThread().getContextClassLoader().getResourceAsStream("upgradeworkbench/Resources/Upgrade_TD_Template.docx");
try {
OutputStream outStream = null;
Stage stage = new Stage();
stage.setTitle("Save");
byte[] buffer= new byte[document.available()];
document.read(buffer);
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialFileName(initialFileName);
if (flag) {
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Microsoft Excel Worksheet", "*.xls"));
} else {
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Microsoft Word Document", "*.docx"));
}
fileChooser.setTitle("Save File");
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
outStream = new FileOutputStream(file);
outStream.write(buffer);
// IOUtils.copy(document, outStream);
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
Can anyone suggest me any different ways to get the proper file.
PS: I am reading the file using InputStream because it is inside the project jar.
PPS: I also tried Files.copy() but it didnt work.
I suggest you never trust on InputStream.available to know the real size of the input, because it just returns the number of bytes ready to be immediately read from the buffer. It might return a small number, but doesn't mean the file is small, but that the buffer is temporarily half-full.
The right algorithm to read an InputStream fully and write it over an OutputStream is this:
int n;
byte[] buffer=new byte[4096];
do
{
n=input.read(buffer);
if (n>0)
{
output.write(buffer, 0, n);
}
}
while (n>=0);
You can use the Files.copy() methods.
Copies all bytes from an input stream to a file. On return, the input stream will be at end of stream.
Use:
Files.copy(document, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
As the class says, the second argument is a Path, not a File.
Generally, since this is 2015, use Path and drop File; if an API still uses File, make it so that it uses it at the last possible moment and use Path all the way.
I've written a JAVA source to zip the files in Oracle DB 11g. The program is working as expected, i.e. it is creating the zip file in the /home/oracle/ directory. But when I download the files to my hard-disk via FTP or email them using the SMTP server, 7Zip refuses to read the contents of the archive and throws the error:-
"Unsupported compression method for DAR.xls"
Am I doing something wrong here? Please help.
Code of the JAVA Source is attached:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "UTLZip" AS
import java.util.zip.*;
import java.io.*;
public class UTLZip
{
public static void compressFile(String infilename, String outfilename)
{
String zipFile = "/home/oracle/DAR.zip";
String[] srcFiles = {"/home/oracle/DAR.xls"};
try {
// create byte buffer
byte[] buffer = new byte[1024];
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
for (int i=0; i < srcFiles.length; i++) {
File srcFile = new File(srcFiles[i]);
FileInputStream fis = new FileInputStream(srcFile);
zos.putNextEntry(new ZipEntry(srcFile.getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
// close the InputStream
fis.close();
}
// close the ZipOutputStream
zos.close();
}
catch (IOException ioe) {
System.out.println("Error creating zip file: " + ioe);
}
}
}
As #peter-lawrey wrote, first check if the zip archive is valid if you uncompress it from the /home/oracle/.
If it is, maybe you have to check if the transfert between your server and your PC didn't corrupt the file (For example, if you tranfered the zip file using ftp protocole, be aware of the data-type used while transfering)
I have merged multiple jpeg files into one single .bin file.
.....
.........
while(true){
if (q.numOfFiles() > 0) {
source = q.getNextFile();
in = new DataInputStream(new BufferedInputStream(new FileInputStream(source)));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
String s = "filename=="+source.getName()+"==filename";
out.write(s.getBytes());
out.flush();
System.out.println("merged--"+source.getName());
}
}
........
........
as you can see i am appending "filename=="+source.getName()+"==filename" after end of each file.
Now i want to separate all those jpegs with their actual file names.
How can i read the separators that I've inserted in the merged files ?
As above in the comments:
Sugestion/answer to adapt your point of view:
Using a single file zip to ship multiple files.
How to create zip in Java
And to extract:
Extract from zip in Java
I could handle the Modified (lastModified) attribute, meaning in the archive I could preserve the Modified attribute of the file.
Here is a sample:
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream( new FileOutputStream(outFilename)));
File f = new File(filename);
long longLastMod = f.lastModified();
FileInputStream in = new FileInputStream(filename);
// Add ZIP entry to output stream.
ZipEntry ze = new ZipEntry(filename);
ze.setTime(longLastMod); // the "magic" to store the Modified date/time of the file
out.putNextEntry( ze );
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
out.close();
Now, the output Zip file will preserve the Modified attribute but it will not preserve the Created or Accessed attributes.
Is there a way to accomplish this?
Is there a way to accomplish this?
No it's not possible. To put it simply: the zip directory doesn't support the attributes.
What you can do, however, is using setExtra(byte[]) and store whatever information you need there. Unfortunately, you'd need a custom extractor to preserve the attributes.
Hope this helps!