Java - FileNotFoundException: /mnt/sdcard: open failed: EISDIR (Is a directory) - java

I'm trying to decompress RAR archive on my Android device from the sd card but I got an error:
java.io.FileNotFoundException: /mnt/sdcard: open failed: EISDIR (Is a directory)
I chose a rar-file and try to decompress it in my sd-card.
Error says that it's not directory but it is. I have no idea how I can fix it.
My code:
public static void unrar(File srcRarFile, String destPath, String password) throws IOException {
if (null == srcRarFile || !srcRarFile.exists()) {
throw new IOException(".");
}
if (!destPath.endsWith(SEPARATOR)) {
destPath += SEPARATOR;
}
Archive archive = null;
OutputStream unOut = null;
try {
archive = new Archive(srcRarFile, password, false);
FileHeader fileHeader = archive.nextFileHeader();
while(null != fileHeader) {
if (!fileHeader.isDirectory())
{
// 1 destDirName destFileName
String destFileName = "";
String destDirName = "";
destFileName = (destPath + fileHeader.getFileNameW()).replaceAll("/", "\\\\");
destDirName = destFileName.substring(0, destFileName.lastIndexOf("\\"));
// 2
File dir = new File(destDirName);
if (!dir.exists() || !dir.isDirectory()) {
dir.mkdirs();
}
//
// ERROR:
unOut = new FileOutputStream(dir);
archive.extractFile(fileHeader, unOut);
unOut.flush();
unOut.close();
}
fileHeader = archive.nextFileHeader();
}
archive.close();
} catch (RarException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(unOut);
}
}

Clear thing. You first create the directory /mnt/sdcard (variable dir is equal to destDirName in your code) and then you try to create a file with the same same. This will not work. Use a name like /mnt/sdcard/abc.rar and it might work. Here is how you create the corresponding File object:
File file = new File(dir, "abc.rar");
Btw: creating a directory called /mnt/sdcard will probably not work due to a lack of permissions. If it's an SD card, Android will do this job for you anyway. If it isn't an SD card, its not a good idea to create a directory with this name.
PS2: After further reviewing your code I see things which are not good style:
You are using the separater variable and indexOf/substring to find the parent directory.
You replace "/" (the android path separator) by "\" which is only used in Windows
You swap between File and string
You can simply get rid of all this by using File.getParent()/File.getParentFile()

Check if you have set permissions in your manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Related

error=24, Too many open files. Deleted files are still open

I have a method that fetch folder file . I only read the filename of the file. At the end of my program I delete the file. The problem is there's a time that "Too many open files" error appear.
I found out that the deleted files are still open.
Here are my codes:
Getting file
private File getFile(String fileName,String filetype) {
File dir = new File("./");
File[] foundFiles = dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith(fileName) && name.endsWith(filetype);
}
});
if(foundFiles.length!=0) {
return foundFiles[0];
}
}
...
File tempFile = this.getFile("versions.sh_",".pid");
String fileName = tempFile.getName();
int startNo = fileName.indexOf("_") + 1;
int endNo = startNo + 5;
pid = fileName.substring(startNo, endNo);
//other logic
Deleting File
if (pidFile != null) {
logger.info("Deleting pidFile file = " + pidFile.toString());
Files.deleteIfExists(pidFile.toPath());
}
Know I want to get rid of the code that open the file but I dont know which part of my code.
Btw this program runs on linux.
----- update
The .pid file is created by script
#!/bin/bash
SCRIPT_PID=`echo $$`
ME=`basename "$0"`
SCRIPT_DIR=$(pwd)
RESULT_TXT=${SCRIPT_DIR}/${ME}_result.txt
PID_FILE=${SCRIPT_DIR}/${ME}_${SCRIPT_PID}.pid
echo $$ > $PID_FILE
The above code keeps the file/folder open in linux. So i used DirectoryStream and try-resources block to implement auto-closable to the used resources.
try (DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get(base),
path -> path.getFileName().toString().startsWith(fileName) && path.toString().endsWith(filetype))) {
paths.forEach(path -> pathList.add(path));
if (pathList.size() > 0) {
file = pathList.get(0).toFile();
}
}

file.listFiles() NullPointerException on build jar

When I run my code on Intellij Idea it work perfectly but when I run my code on the .jar (so build) there is a NullPointerException. Did someone know why and how to fix this ?
File folder = new
File(Main.class.getClassLoader().getResource("assets/maps/").getPath());
System.out.println(folder);
System.out.println(folder.listFiles());
for (File file : folder.listFiles()) {
if(file.getName().endsWith(".btdm"))
maps.add(getMap(file));
}
console :
file:\E:\Programmation\BabyTD\out\artifacts\BabyTD_jar\BabyTD.jar!\assets\maps
null
Exception in thread "main" java.lang.NullPointerException
at fr.picearth.Main.getMaps(Main.java:51)
at fr.picearth.Main.main(Main.java:26)
If folder is not a folder or cannot be accessed for some reason (including the fact that java.io.File cannot open jar or other zip files like ordinary folders), then listFiles() will return null. You've already seen this in your print out. You have to check prior to iterating:
File[] files = folder.listFiles();
if (files != null)
for (File file : files)
if(file.getName().endsWith(".btdm"))
maps.add(getMap(file));
However, you probably want to work with java.util.zip.ZipFile instead
Assuming assets/maps/ folder is part of your jar file, then you won't be able to access like any other folder on your drive.
IDE consider it as folder/file on drive so it works with getResource.
What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir.
try getResourceAsStream inplace of getResource
String respath = "/path_to_file";
InputStream in = sample2.class.getResourceAsStream(respath);
if ( in == null ){
throw new Exception("resource not found: " + respath);
}
InputStreamReader inr = new InputStreamReader(in, "UTF-8");
int len;
char cbuf[] = new char[2048];
while ((len = inr.read(cbuf, 0, cbuf.length)) != -1) {
// do something with cbuf
}
EDIT 2 :
if you are using java 7+ then you can also use
private Path getFolderPath() throws URISyntaxException, IOException {
URI uri = getClass().getClassLoader().getResource("folder").toURI();
if ("jar".equals(uri.getScheme())) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
return fileSystem.getPath("path/to/folder/inside/jar");
} else {
return Paths.get(uri);
}
}

Moving from one directory to another java [duplicate]

How do you move a file from one location to another? When I run my program any file created in that location automatically moves to the specified location. How do I know which file is moved?
myFile.renameTo(new File("/the/new/place/newName.file"));
File#renameTo does that (it can not only rename, but also move between directories, at least on the same file system).
Renames the file denoted by this abstract pathname.
Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful.
If you need a more comprehensive solution (such as wanting to move the file between disks), look at Apache Commons FileUtils#moveFile
With Java 7 or newer you can use Files.move(from, to, CopyOption... options).
E.g.
Files.move(Paths.get("/foo.txt"), Paths.get("bar.txt"), StandardCopyOption.REPLACE_EXISTING);
See the Files documentation for more details
Java 6
public boolean moveFile(String sourcePath, String targetPath) {
File fileToMove = new File(sourcePath);
return fileToMove.renameTo(new File(targetPath));
}
Java 7 (Using NIO)
public boolean moveFile(String sourcePath, String targetPath) {
boolean fileMoved = true;
try {
Files.move(Paths.get(sourcePath), Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
fileMoved = false;
e.printStackTrace();
}
return fileMoved;
}
File.renameTo from Java IO can be used to move a file in Java. Also see this SO question.
To move a file you could also use Jakarta Commons IOs FileUtils.moveFile
On error it throws an IOException, so when no exception is thrown you know that that the file was moved.
Just add the source and destination folder paths.
It will move all the files and folder from source folder to
destination folder.
File destinationFolder = new File("");
File sourceFolder = new File("");
if (!destinationFolder.exists())
{
destinationFolder.mkdirs();
}
// Check weather source exists and it is folder.
if (sourceFolder.exists() && sourceFolder.isDirectory())
{
// Get list of the files and iterate over them
File[] listOfFiles = sourceFolder.listFiles();
if (listOfFiles != null)
{
for (File child : listOfFiles )
{
// Move files to destination folder
child.renameTo(new File(destinationFolder + "\\" + child.getName()));
}
// Add if you want to delete the source folder
sourceFolder.delete();
}
}
else
{
System.out.println(sourceFolder + " Folder does not exists");
}
Files.move(source, target, REPLACE_EXISTING);
You can use the Files object
Read more about Files
You could execute an external tool for that task (like copy in windows environments) but, to keep the code portable, the general approach is to:
read the source file into memory
write the content to a file at the new location
delete the source file
File#renameTo will work as long as source and target location are on the same volume. Personally I'd avoid using it to move files to different folders.
Try this :-
boolean success = file.renameTo(new File(Destdir, file.getName()));
Wrote this method to do this very thing on my own project only with the replace file if existing logic in it.
// we use the older file i/o operations for this rather than the newer jdk7+ Files.move() operation
private boolean moveFileToDirectory(File sourceFile, String targetPath) {
File tDir = new File(targetPath);
if (tDir.exists()) {
String newFilePath = targetPath+File.separator+sourceFile.getName();
File movedFile = new File(newFilePath);
if (movedFile.exists())
movedFile.delete();
return sourceFile.renameTo(new File(newFilePath));
} else {
LOG.warn("unable to move file "+sourceFile.getName()+" to directory "+targetPath+" -> target directory does not exist");
return false;
}
}
Please try this.
private boolean filemovetoanotherfolder(String sourcefolder, String destinationfolder, String filename) {
boolean ismove = false;
InputStream inStream = null;
OutputStream outStream = null;
try {
File afile = new File(sourcefolder + filename);
File bfile = new File(destinationfolder + filename);
inStream = new FileInputStream(afile);
outStream = new FileOutputStream(bfile);
byte[] buffer = new byte[1024 * 4];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
// delete the original file
afile.delete();
ismove = true;
System.out.println("File is copied successful!");
} catch (IOException e) {
e.printStackTrace();
}finally{
inStream.close();
outStream.close();
}
return ismove;
}

Retrieve the web app root path in JSF Managed Bean

Im trying to access the example/web folder (see below in the image) in a jsf managed bean but cant seem to find a way to do it
thx
Try
FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath()
for build relative url's to resources in your app.
If you want the real path...
ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
String realPath = ctx.getRealPath("/");
If you want to get it as a File for some reason, then you need ExternalContext#getRealPath(). This converts a relative web path to an absolute disk file system. Since you need the web's root folder, just pass in /:
String absoluteWebPath = externalContext.getRealPath("/");
File webRoot = new File(absoluteWebPath);
// ...
Unrelated to the concrete problem, whatever functional requirement you've had in mind for which you thought that having an absolute local disk file system path to the web folder is the right solution, it has most definitely to be solved differently. And indeed, as per your comment on the other answer,
because Im trying to upload some file inside the folder and using the relative path
you're going the wrong path. You should not store uploaded files in there if you intend to keep them longer than the webapp's deployment lifetime. Whenever you redeploy the webapp (and on some server configs even when you restart the server), the uploaded files would get completely lost, simply because they are not contained as part of the original WAR file. Even more, some heavy server configs don't expand the WAR on disk at all, but in memory instead, the getRealPath() would then always return null.
Rather store it in a fixed disk file system path outside the server's deploy folder. Add that path in turn as a new server context or docroot, so that it's accessible on a different (virtual) context path. Or homegrow a servlet which gets an InputStream of it from disk and writes it to OutputStream of the response. See also this related answer: Uploaded image only available after refreshing the page
Try:
String relativePath="/resources/temp/";
String absolutePath= FacesContext.getCurrentInstance.getExternalContext().getRealPath(relativePath);
File file = new File(absolutePath);
to get real path.
Create a tmp file in resources/temp/ to avoid any exception.
Just wanted to thank Balus C. Code Java with JSP, in Tomcat/Tomee server I the following code that works:
private Boolean SaveUserItemImage(Part ui, String bid) throws IOException {
Boolean fileCreate = false;
OutputStream out = null;
InputStream filecontent = null;
ExternalContext ctx = context().getExternalContext();
String absoluteWebPath = ctx.getRealPath("/");
String resource_path = absoluteWebPath + "\\resources\\";
String image_path = resource_path + "\\" + this.itemType + "_images\\";
String buildFileName = image_path + bid + "_" + getFileName(ui);
File files = null;
try {
files = new File(buildFileName);
fileCreate = true;
} catch (Exception ex) {
System.out.println("Error in Creating New File");
Logger.getLogger(ItemBean.class.getName()).log(Level.SEVERE, null, ex);
}
if (fileCreate == true) {
if (files.exists()) {
/// User may be using same image file name but has been editted
files.delete();
}
try {
out = new FileOutputStream(files);
filecontent = ui.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = filecontent.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
fileCreate = true;
} catch (FileNotFoundException fne) {
fileCreate = false;
Logger.getLogger(ItemBean.class.getName()).log(Level.SEVERE, "SaveUserItemImage", fne);
} finally {
if (out != null) {
out.close();
}
if (filecontent != null) {
filecontent.close();
}
files = null;
}
}
return fileCreate;
}

How do I move a file from one location to another in Java?

How do you move a file from one location to another? When I run my program any file created in that location automatically moves to the specified location. How do I know which file is moved?
myFile.renameTo(new File("/the/new/place/newName.file"));
File#renameTo does that (it can not only rename, but also move between directories, at least on the same file system).
Renames the file denoted by this abstract pathname.
Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful.
If you need a more comprehensive solution (such as wanting to move the file between disks), look at Apache Commons FileUtils#moveFile
With Java 7 or newer you can use Files.move(from, to, CopyOption... options).
E.g.
Files.move(Paths.get("/foo.txt"), Paths.get("bar.txt"), StandardCopyOption.REPLACE_EXISTING);
See the Files documentation for more details
Java 6
public boolean moveFile(String sourcePath, String targetPath) {
File fileToMove = new File(sourcePath);
return fileToMove.renameTo(new File(targetPath));
}
Java 7 (Using NIO)
public boolean moveFile(String sourcePath, String targetPath) {
boolean fileMoved = true;
try {
Files.move(Paths.get(sourcePath), Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
fileMoved = false;
e.printStackTrace();
}
return fileMoved;
}
File.renameTo from Java IO can be used to move a file in Java. Also see this SO question.
To move a file you could also use Jakarta Commons IOs FileUtils.moveFile
On error it throws an IOException, so when no exception is thrown you know that that the file was moved.
Just add the source and destination folder paths.
It will move all the files and folder from source folder to
destination folder.
File destinationFolder = new File("");
File sourceFolder = new File("");
if (!destinationFolder.exists())
{
destinationFolder.mkdirs();
}
// Check weather source exists and it is folder.
if (sourceFolder.exists() && sourceFolder.isDirectory())
{
// Get list of the files and iterate over them
File[] listOfFiles = sourceFolder.listFiles();
if (listOfFiles != null)
{
for (File child : listOfFiles )
{
// Move files to destination folder
child.renameTo(new File(destinationFolder + "\\" + child.getName()));
}
// Add if you want to delete the source folder
sourceFolder.delete();
}
}
else
{
System.out.println(sourceFolder + " Folder does not exists");
}
Files.move(source, target, REPLACE_EXISTING);
You can use the Files object
Read more about Files
You could execute an external tool for that task (like copy in windows environments) but, to keep the code portable, the general approach is to:
read the source file into memory
write the content to a file at the new location
delete the source file
File#renameTo will work as long as source and target location are on the same volume. Personally I'd avoid using it to move files to different folders.
Try this :-
boolean success = file.renameTo(new File(Destdir, file.getName()));
Wrote this method to do this very thing on my own project only with the replace file if existing logic in it.
// we use the older file i/o operations for this rather than the newer jdk7+ Files.move() operation
private boolean moveFileToDirectory(File sourceFile, String targetPath) {
File tDir = new File(targetPath);
if (tDir.exists()) {
String newFilePath = targetPath+File.separator+sourceFile.getName();
File movedFile = new File(newFilePath);
if (movedFile.exists())
movedFile.delete();
return sourceFile.renameTo(new File(newFilePath));
} else {
LOG.warn("unable to move file "+sourceFile.getName()+" to directory "+targetPath+" -> target directory does not exist");
return false;
}
}
Please try this.
private boolean filemovetoanotherfolder(String sourcefolder, String destinationfolder, String filename) {
boolean ismove = false;
InputStream inStream = null;
OutputStream outStream = null;
try {
File afile = new File(sourcefolder + filename);
File bfile = new File(destinationfolder + filename);
inStream = new FileInputStream(afile);
outStream = new FileOutputStream(bfile);
byte[] buffer = new byte[1024 * 4];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
// delete the original file
afile.delete();
ismove = true;
System.out.println("File is copied successful!");
} catch (IOException e) {
e.printStackTrace();
}finally{
inStream.close();
outStream.close();
}
return ismove;
}

Categories