I am trying to export zip files to a directory and running into an IOException stating that the file path cannot be found. I am aware that this means that the parent directory does not exist usually, however debugging the line where the file is being written file.getParentFile().exists() returns true, so this is not my issue. To further complicate matters, this only occurs for approximately half of the files written. It is always the same files that fail when unzipping via java, but unzipping them via windows always successfully works.
Here is the code I am using:
ZipInputStream zis =
new ZipInputStream(new ByteArrayInputStream(zipFile));
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
if(!newFile.isDirectory()) {
newFile.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(newFile); //Exception occurs here
//newFile.getParentFile().exists() returns true
//copying the path for newFile.getParentFile() into my file browser leads me to a valid, existing folder
//I have tried newFile.createNewFile() and that errors with a similar exception
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
results.add(new Foo());
}
ze = zis.getNextEntry();
}
Example exception:
java.io.FileNotFoundException: \\foo\foo\foo\foo\foo\foo\foo.pdf (The system cannot find the path specified)
Some more notes about the system: the file system is a remote network drive, the system is running windows, and the account has full write access to the drive. I have also verified that naming a file foo.pdf (copy and pasting the name of the file intended to be written) does not cause any issue either.
The issue is that zip files can have trailing spaces in their paths. For example, "Test whatever .zip" could be the file name so java sees the folder as "/Test whatever /" and it tries to create that folder. Windows tells java that it succeeded, but really it created a folder at "/Test Whatever/". When dealing with folders, the file IO has no issue with this, but when writing files, it completely bombs as it's looking for the path explicitly. It does not truncate the extra white space the same way it does when dealing with folders, as you would expect.
Here is the code I used to resolve it:
String path = (outputFolder + File.separator + fileName).replace(" ", "");
File newFile = new File(path);
Related
i upload a csv file from client side and i want to create this file in server side.
Here is my function
public void uploadFile(FileUploadEvent e) throws IOException{
UploadedFile uploadedCsv=e.getFile();
String filePath="//ipAdress:/home/cg/Temp/input/ressource.csv";
byte[] bytes=null;
if(uploadedCsv != null){
bytes=uploadedCsv.getContents();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
String filename = FilenameUtils.getName(uploadedCsv.getFileName());
stream.write(bytes);
stream.close();
}
}
When I want to write the file I get this exception (No such file or directory)
SEVERE: java.io.FileNotFoundException: /ipAdress:/home/cg/Temp/input/ressource.csv (No such file or directory)
Knowing that the / home / cg / Temp / input path is created on the server.
Could you try:
String filePath="////ipAdress/home/cg/Temp/input/ressource.csv";
Instead of:
String filePath="//ipAdress:/home/cg/Temp/input/ressource.csv";
And this:
new File(new URI(filePath))
Instead of:
new File(filePath)
Or you can use jcif API How can I open a UNC path from Linux in Java?
I would use the <file>.mkdirs(); at one level above the file itself.
So do String filePath="//ipAdress:/home/cg/Temp/input
File directory = new File(filePath);
directory.mkdirs();
You can then make the file
File tempFile = new File(directory + "/ressource.csv);
Or a cleaner solution all around is just use Files.createTempFile(prefix, suffix) this will create a file in the temp directory of the system.
The reason that your code does not work is that you are trying to use a UNC pathname on Linux. Linux does not support UNC pathnames ... natively. They are a Windows-ism.
Here's your example
"//ipAdress:/home/cg/Temp/input/ressource.csv";
If you try to use that on Linux, the OS will look for a directory in the root directory of the file system. The directory it will look for will have the name ipaddress: ... noting that there is a colon in the directory name!
That will most likely fail ... because no directory with that name exists in the / directory.. And the exception message you are getting is consistent with this diagnosis.
If you are doing this because you are trying to push files out to other systems then you are going to do it some other way. For example:
Use NFS and mount the other system's file systems on the server.
Use a Java implementation of UNC names; e.g. How can I open a UNC path from Linux in Java?
(Which ever way you do it, there are security issues to consider!)
trying this new File(new URI(filePath)) instead of new File(filePath) i get this erreur. SEVERE: java.lang.IllegalArgumentException: URI is not absolute
It won't work. A UNC name is NOT a valid URL or URI.
I have found a solution for this problem, but it's not smart and still and it works
String fileName="ressource.csv";
File f = new File(System.getProperty("user.home") + "/Temp/input",fileName);
if (f.exists() && !f.canWrite())
throw new IOException("erreur " + f.getAbsolutePath());
if (!f.exists())
Files.createFile(f.toPath());
if (!f.isFile()) {
f.createNewFile(); // Exception here
} else {
f.setLastModified(System.currentTimeMillis());
}
Pending a more intelligent solution
I am trying to get the following code to work properly. It always prints the output from the catch block, even though the output that is only printed if the file exists, is printed.
String outputFile = "/home/picImg.jpg";
File outFile = new File(outputFile);
if(outFile.exists)
newStatus(" File does indeed exist");
FileOutputStream fos;
try {
fos = new FileOutputStream(outFile);
fos.write(response);
fos.close();
return outputFile;
} catch (FileNotFoundException ex) {
newStatus("Error: Couldn't find local picture!");
return null;
}
In the code response is a byte[] containig a .jpg image from a URL. Overall I am trying to download an image from a URL and save it to the local file system and return the path. I think the issue has to do with read/write permissions within /home/. I chose to write the file there because I'm lazy and didn't want to find the username to find the path /home/USER/Documents. I think I need to do this now.
I notice in the terminal I can do cd ~ and get to /home/USER/. Is there a "path shortcut" I can use within the file name so that I can read/write in a folder that has those permissions?
No. The ~ is expanded by the shell. In Java File.exists() is a method, you can use File.separatorChar and you can get a user's home folder with System property "user.home" like
String outputFile = System.getProperty("user.home") + File.separatorChar
+ "picImg.jpg";
File outFile = new File(outputFile);
if (outFile.exists())
Edit
Also, as #StephenP notes below, you might also use File(File parent, String child) to construct the File
File outFile = new File(System.getProperty("user.home"), "picImg.jpg");
if (outFile.exists())
~ expansion is a function of your shell and means nothing special for the file system. Look for Java System Properties "user.home"
Java provides a System property to get the user home directory: System.getProperty("user.home");.
The advantage of this is, that it works for every operating system that can run the Java virtual machine.
More about System properties: Link.
I need to create temporary directory but I'm always getting access denied when I try to create a file into the temporary directory.
java.io.FileNotFoundException: C:\tmpDir7504230706415790917 (Access Denied)
here's my code:
public static File createTempDir() throws IOException {
File temp = File.createTempFile("tmpDir", "", new File("C:/"));
temp.delete();
temp.mkdir();
return temp;
}
public File createFile(InputStream inputStream, File tmpDir ) {
File file = null;
if (tmpDir.isDirectory()) {
try {
file = new File(tmpDir.getAbsolutePath());
// write the inputStream to a FileOutputStream
OutputStream out = new FileOutputStream(file);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
inputStream.close();
out.flush();
out.close();
System.out.println("New file created!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
return file;
}
I'm working on a web application and I'm using tomcat. Is there a way to create temporary file on tomcat server memory? I know that's bizarre, but I don't know ... maybe it's possible.
You could use Tomcat's temp folder.
If you use
<%=System.getProperty("java.io.tmpdir")%>
in a JSP you can get path to it.
This line in your code says create a file whose name starts with text "tmpDir" in the directory "C:\". That is not what you want.
File temp = File.createTempFile("tmpDir","",new File("C:/"));
The operating system is properly disallowing that because C:\ is a protected directory. Use the following instead:
File temp = File.createTempFile("tmp",null);
This will let Java determine the appropriate temporary directory. Your file will have the simple prefix "tmp" followed by some random text. You can change "tmp" to anything meaningful for your app, in case you need to manually clean out these temp files and you want to be able to quickly identify them.
You usually cannot write onto C:\ directly due to the default permission setting. I sometime have permission issue for doing so. However, you can write your temporary file in your user folder. Usually, this is C:\Documents and Settings\UserName\ on XP or C:\Users\UserName\ on vista and Windows 7. A tool called SystemUtils from Apache Lang can be very useful if you want to get the home directory depending on OS platform.
For example:
SystemUtils.getUserDir();
SystemUtils.getUserHome();
Update
Also, you create a temp file object but you call mkdir to make it into a directory and try to write your file to that directory object. You can only write a file into a directory but not on the directory itself. To solve this problem, either don't call temp.mkdir(); or change this file=new File(tmpDir.getAbsolutePath()); to file=new File(tmpDir, "sometempname");
On Linux with tomcat7 installation:
So if you are running web application this is the temp directory Tomcat uses for the creation of temporary files.
TOMCAT_HOME/temp
In my case TOMCAT_HOME => /usr/share/tomcat7
If you are running Java program without tomcat, by default it uses /tmp directory.
Not sure if it affects but i ran this command too.
chmod 777 on TOMCAT_HOME/temp
I tried the java.util.zip package, it is too slow.
Then I found LZMA SDK and 7z jbinding but they are also lacking something.
The LZMA SDK does not provide a kind of documentation/tutorial of how-to-use, it is very frustrating. No javadoc.
While the 7z jbinding does not provide a simple way to extract only 1 file, however, it only provide way to extract all the content of the zip file. Moreover, it does not provide a way to specify a location to place the unzipped file.
Any idea please?
What does your code with java.util.zip look like and how big of a zip file are you dealing with?
I'm able to extract a 4MB entry out of a 200MB zip file with 1,800 entries in roughly a second with this:
OutputStream out = new FileOutputStream("your.file");
FileInputStream fin = new FileInputStream("your.zip");
BufferedInputStream bin = new BufferedInputStream(fin);
ZipInputStream zin = new ZipInputStream(bin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
if (ze.getName().equals("your.file")) {
byte[] buffer = new byte[8192];
int len;
while ((len = zin.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
break;
}
}
I have not benchmarked the speed but with java 7 or greater, I extract a file as follows.
I would imagine that it's faster than the ZipFile API:
A short example extracting META-INF/MANIFEST.MF from a zip file test.zip:
// file to extract from zip file
String file = "MANIFEST.MF";
// location to extract the file to
File outputLocation = new File("D:/temp/", file);
// path to the zip file
Path zipFile = Paths.get("D:/temp/test.zip");
// load zip file as filesystem
try (FileSystem fileSystem = FileSystems.newFileSystem(zipFile)) {
// copy file from zip file to output location
Path source = fileSystem.getPath("META-INF/" + file);
Files.copy(source, outputLocation.toPath());
}
Use a ZipFile rather than a ZipInputStream.
Although the documentation does not indicate this (it's in the docs for JarFile), it should use random-access file operations to read the file. Since a ZIPfile contains a directory at a known location, this means a LOT less IO has to happen to find a particular file.
Some caveats: to the best of my knowledge, the Sun implementation uses a memory-mapped file. This means that your virtual address space has to be large enough to hold the file as well as everything else in your JVM. Which may be a problem for a 32-bit server. On the other hand, it may be smart enough to avoid memory-mapping on 32-bit, or memory-map just the directory; I haven't tried.
Also, if you're using multiple files, be sure to use a try/finally to ensure that the file is closed after use.
Basically my problem is a that I need to copy an uploaded file (which is placed in a temporary folder on my server providers Tomcat ie. not a local Tomcat).
The code I'm using works when I deploy my project on my local machine but stops working when I deploy it live.
I've found out that it has something to with my permissions in java.policy.
What I need to find out is how do I get access to the folder in which Tomcat stores the temporary file using Java.
When reading catalina.out this is the clue that the log gives me.
/usr/local/tomcat/work/Catalina/project name here/context of project here/upload_490341a6_12b1d397355_76ce_00000001.tmp
I'm thinking somewhere along the lines (note: this is not an actual method :P )
ServletActionContext.getContext().getSuperHiddenTemporaryCatalog();
The code snippet at the bottom has one flaw.
sourceFile and targetFile points to the same directory at the moment.
I want the sourceFile path to be the temporary tomcat-folder.
Thanks in advance! :D
public String saveImage(File file, String uploadedFileName) {
String path = ServletActionContext.getServletContext().getRealPath("images");
System.out.println(path);
String fullFileName = path + "/" + uploadedFileName;
System.out.println(fullFileName);
boolean successful = false;
try {
File sourceFile = new File(fullFileName);
File targetFile = new File(path + "/" + uploadedFileName);
InputStream in = new FileInputStream(sourceFile);
OutputStream out = new FileOutputStream(targetFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (Exception e) {
successful = false;
e.printStackTrace();
}
if (successful) {
return "context of project/images/" + uploadedFileName;
} else {
return "";
}
}
File tempDir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
should give you access to your temporary directory in Tomcat. It would be strange if you could not at least read files from there.
The code I'm using works when I deploy my project on my local machine but stops working when I deploy it live. I've found out that it has something to with my permissions in java.policy.
Yes. This is an example of a Java security sandbox.
What I need to find out is how do I get access to the folder in which Tomcat stores the temporary file using Java.
You cannot circumvent the security sandbox (modulo some unpatched bug in your JVM). What you need to do is change the "java.policy" settings so that your webapp has permission copy the file to where it needs to be copied. You may need to discuss this with whoever has done the security design, etc for your production Tomcats.