I'm having some issues with removing files after moving them to an ftp site. In a previous process I am generating files and putting them in a folder. This process should upload every file to the ftp site and then delete the local copy. For reasons I can't figure out the delete is failing but I'm not getting any sort of error message or exception. Originally I had the file.delete() call right after the ftp.put() but I moved it to it's current location thinking that maybe the file was locked by jsch and putting the call there would fix it. That doesn't seem to be the case. Ideally the call would go back there so I don't need to have two "for" loops.
If you also happen to know why the overwrite is not working that would be a bonus. When i look at the files uploaded through an actual FTP program the rights are rw-rw-rw. The existing files on the server were already uploaded through this process.
Here is the code:
JSch jsch = new JSch();
Session session = null;
try {
File sourceDir = new File(certSourceFolder);
if (!sourceDir.exists()) {
sourceDir.mkdirs();
}
session = jsch.getSession(ftpUser, ftpServer, 22);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(ftpPassword);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp ftp = (ChannelSftp) channel;
ftp.cd(certDestFolder);
for (File file : sourceDir.listFiles()) {
if (file.isFile()) {
try {
ftp.put(new FileInputStream(file), file.getName(), ChannelSftp.OVERWRITE);
} catch (SftpException ex) {
//The overwrite is not working. For now I'm just going to trap the error and move on. This really shouldn't happen ever since I delete the file once uploaded.
if (!ex.getMessage().equalsIgnoreCase("Permission denied"))
throw ex;
}
}
}
ftp.exit();
session.disconnect();
//TODO: this is not working. figure out why. If possible get rid of this and move the file.delete up to after ftp.put
for (File file : sourceDir.listFiles()) {
if (file.isFile()) {
file.delete();
}
}
} catch (Exception e) {
DefaultLogger.logException("CertificateFileTransfer", e);
}
}
You must close the file after using it, otherwise, it will be locked by the current using component.
Change this line:
ftp.put(new FileInputStream(file)...
To a finally clause that calling close on the stream in order to ensure the release of the file in any case (good or exception):
finally{
fileInput.close();
}
To recap:
FileInputStream fileInput = null;
try {
fileInput = new FileInputStream(file);
ftp.put(fileInput, file.getName(), ChannelSftp.OVERWRITE);
} catch (SftpException ex) {
if (!ex.getMessage().equalsIgnoreCase("Permission denied"))
throw ex;
}
finally{
if(fileInput != null){
fileInput.close();
}
}
From docs:
close() Closes this file input stream and releases any system
resources associated with the stream.
Related
I have created a file and I want to write in bytes in this file but it's not working. Where is the problem?
public void writeFileExternalStorage() {
File file = new File(getExternalFilesDir(null), "hhh.txt");
try {
if(!file.exists())
file.createNewFile();
FileOutputStream outputStream ;
outputStream = new FileOutputStream(file, true);
outputStream.write(files.getBytes());
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
The createNewFile call will return true if it has successfully created the file. You should check the result of the call, and log an error if it is false.
According to the documentation for getExternalFilesDir (javadoc):
[it m]ay return null if shared storage is not currently available.
If that happens you will call new File(null, "hhh.txt"). That is equivalent to new File("hhh.txt") (javadoc), so the file would be created in the app's "current user directory".
hey i want to upload a file to a directory called 'screenshots' on my webserver via FTP using java. I have been using this code and it says that it stores the file successfully and connected successfully but when i check my screenshots directory via the cpanel i dont see the file that was uploaded any help?
public static void uploadFilee() {
FTPClient client = new FTPClient();
FileInputStream fis = null;
try {
client.connect("****************");
client.login("********", "********");
System.out.println("Connected Successfully");
String filename = "C:/Users/Christian/Desktop/screenshots/img_" + queueInfo.get("SessionID");
fis = new FileInputStream(filename);
client.storeFile(filename, fis);
System.out.println("Stored File Successfully");
client.logout();
} catch (IOException e) {
System.out.println("Error_1");
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
client.disconnect();
} catch (IOException e) {
System.out.println("Error_2");
e.printStackTrace();
}
}
}
`
You may want to review this page
http://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html#_storeFile(java.lang.String,java.lang.String,java.io.InputStream)
you have your statements such as storefile in a try statement, but if they fail, they return false, not an exception.
changing your code to inspect the return values of each function should help you find where your problem lies.
I have data coming from a bluetooth device, the data is being stored in an inputstream. I am taking the data from the inputstream and generating a graphic with Jfreechart. Whenever I turn off the bluetooth device the data keeps coming from the inputstream and the graphic continues being generated.
I need the data and the graphic to stop when I turn off the bluetooth device.
I am using Java.
Every InputStream has a close() method that should do exactly what you need ... if you can detect that the device is turned off, that is.
The docs on this.
Reference link : Closing java InputStream
which resolved my problem too.
Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
props.load(fis);
//omitted.
} catch (Exception ex) {
//omitted.
} finally {
try {
fis.close();
fis=null;
} catch (IOException ioex) {
//omitted.
}
}
I am trying to check if a certain java.io.File is open by an external program. On windows I use this simple trick:
try {
FileOutputStream fos = new FileOutputStream(file);
// -> file was closed
} catch(IOException e) {
// -> file still open
}
I know that unix based systems allow to open files in multiple processes... Is there a similar trick to achieve the same result for unix based systems ?
Any help / hack highly appreciated :-)
Here's a sample how to use lsof for unix based systems:
public static boolean isFileClosed(File file) {
try {
Process plsof = new ProcessBuilder(new String[]{"lsof", "|", "grep", file.getAbsolutePath()}).start();
BufferedReader reader = new BufferedReader(new InputStreamReader(plsof.getInputStream()));
String line;
while((line=reader.readLine())!=null) {
if(line.contains(file.getAbsolutePath())) {
reader.close();
plsof.destroy();
return false;
}
}
} catch(Exception ex) {
// TODO: handle exception ...
}
reader.close();
plsof.destroy();
return true;
}
Hope this helps.
This one should also work for Windows systems. But attention, does not work for Linux!
private boolean isFileClosed(File file) {
boolean closed;
Channel channel = null;
try {
channel = new RandomAccessFile(file, "rw").getChannel();
closed = true;
} catch(Exception ex) {
closed = false;
} finally {
if(channel!=null) {
try {
channel.close();
} catch (IOException ex) {
// exception handling
}
}
}
return closed;
}
You can run from Java program the lsof Unix utility that tells you which process is using a file, then analyse its output. To run a program from Java code, use, for example, Runtime, Process, ProcessBuilder classes. Note: your Java program won't be portable in this case, contradicting the portability concept, so think twice whether you really need this :)
Thanks for the original suggestion. I have one small upgrade that is somewhat important to that method:
FileOutputStream fos = null;
try {
// Make sure that the output stream is in Append mode. Otherwise you will
// truncate your file, which probably isn't what you want to do :-)
fos = new FileOutputStream(file, true);
// -> file was closed
} catch(IOException e) {
// -> file still open
} finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Cheers,
Gumbatron
You can try this semaphore type code for a file lock by #ZZ Coder
File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
FileLock lock = channel.lock();
try {
lock = channel.tryLock();
// Ok. You get the lock
} catch (OverlappingFileLockException e) {
// File is open by someone else
} finally {
lock.release();
}
First off, I am not trying to write to the SDCard. I want to write some information to a file that persists between uses of the app. It is essentially a file to hold favorites of the particular user. Here is what the code looks like:
try {
File file = new File("favorites.txt");
if (file.exists()) {
Log.d(TAG, "File does exist.");
fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis));
}
else {
Log.d(TAG, "File does not exist.");
return favDests;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
When running this code, we always get the "File does not exist." message in our DDMS log.
We have also tried the following code to no avail:
try {
File file = new File(GoLincoln.FAV_DEST_FILE);
fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
It is this second portion of code that results in the FileNotFoundException.
I have read multiple tutorials on writing and reading files on Android and I believe I am following them pretty closely, so I am not sure why this code doesn't work successfully. I appreciate any help!
You shouldn't use the File class directly. Use Activity.getCacheDir() to get the cache dir which is specific to your application. Then use new File(cachedir, "filename.tmp") to create the file.
Preferences and SQLLite will both allow you to have persistent data without managing your own files.
To use shared preferences you grab it from your context, then you edit the values like so
mySharedPreferences = context.getSharedPreferences("DatabaseNameWhateverYouWant", 0);
mySharedPreferences.getEditor().putString("MyPreferenceName", "Value").commit();
To get a preference out
mySharedPreferences.getString("MyPreferenceName", "DefaultValue");
This is really the simplest way to do basic preferences, much easier then doing a file. More then strings are supported, most basic data types are available to be added to the Preferences class.