In the below code statement:
SmbFileInputStream din==new SmbFileInputStream(src);
I am trying to create a SmbFileInputStream object. This will works fine if SmbFile 'src' is a file, but if 'src' is a smb Directory then it throws exception:
jcifs.smb.SmbException: Access is Denied.
at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:622)
at jcifs.smb.SmbTransport.send(SmbTransport.java:722)
at jcifs.smb.SmbSession.send(SmbSession.java:262)
at jcifs.smb.SmbTree.send(SmbTree.java:119)
at jcifs.smb.SmbFile.send(SmbFile.java:785)
at jcifs.smb.SmbFile.open0(SmbFile.java:1009)
at jcifs.smb.SmbFile.open(SmbFile.java:1026)
at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:73)
at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:65)
at testhelp.main(testhelp.java:25)
What is wrong with this code? or where am I going wrong?
Hi please check this code:
case DOWNLOAD2:
/*This code snippet is used to download a file/folder from smb nETWORK to android sd card.
when I run this code its throwing some exception. It have commented where ever necessary. rest of the code is self
explanatory. So please go through the code and please tell why this exception is thrown.
IF POSSIBLE PLEASE ADD A PROGRESS BAR WHICH SHOULD HELP USER SAYING SOME WORK IS GOING ON.
I have tried including a progress bar, but its not working. I ve read some materials related to this,
but every thing makes use threads. I am not that good at threads. So is it possible to include a progess bar,
without using threads?If possible please help me to do it.
And this code is working file for smb files, I dont know why its throwing exception in case of directories.
Please see why this is throwing exception..
So please see that the modified code contains:
a)no exceptions
b)a progress bar(more specifically a horizontal bar)*/
/*exception thrown:
jcifs.smb.SmbException: Access is Denied.
at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:622)
at jcifs.smb.SmbTransport.send(SmbTransport.java:722)
at jcifs.smb.SmbSession.send(SmbSession.java:262)
at jcifs.smb.SmbTree.send(SmbTree.java:119)
at jcifs.smb.SmbFile.send(SmbFile.java:785)
at jcifs.smb.SmbFile.open0(SmbFile.java:1009)
at jcifs.smb.SmbFile.open(SmbFile.java:1026)
at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:73)
at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:65)
at testhelp.main(testhelp.java:25)*/
StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
//if sd card is mounted then only this operation occur:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
//object.getCount() gets the number of objects in list view
for(int i=0;i<object.getCount();i++)
{
//for each object in list view, if it is checked:
if(object.getter(i)==true)
{
SmbFileInputStream din=null;
FileOutputStream dout=null;
try
{
//I have used a hash table, which maps list view name with smb object
SmbFile src=map.get(object.getItem(i));
long blockSize = statFs.getBlockSize();
long freeSize = statFs.getFreeBlocks()*blockSize;
long diff=freeSize-src.length();
boolean can=false;
if(!(diff<0))
{
can=true;
}
if(!src.isHidden() && can)
{
try
{
if(src.isFile())
{
din=new SmbFileInputStream(src);
dout=new FileOutputStream(Environment.getExternalStorageDirectory()+"/"+src.getName());
}
else
{
din=new SmbFileInputStream(src);
File outputFile = new File(Environment.getExternalStorageDirectory()+"/"+src.getName()); // ADDED
outputFile.mkdirs(); // ADDED
dout=new FileOutputStream(outputFile); // CHANGED
}
int c;
while((c=din.read())!=-1)
{
dout.write(c);
}
}
finally
{
if (din != null)
{
din.close();
}
if (dout != null)
{
dout.close();
}
}
}
else
{
Toast.makeText(this,src.getName()+" cannot be downloaded",Toast.LENGTH_LONG).show();
}
}
catch(IOException e)
{
Toast.makeText(this,"DOWNLOAD FAILED--IO EXCEPTION\n"+e,Toast.LENGTH_LONG).show();
}
}
}
}
else
{
Toast.makeText(this,"DOWNLOAD FAILED--NO SD CARD FOUND",Toast.LENGTH_LONG).show();
}
return true;
You can't create an SmbFileInputStream for a directory, because you can't read/write directly to the directory object. A directory doesn't have any content, at least not in the same way that a file has content.
If you're trying to read the contents of a directory, you should probably be using SmbFile instead (for example, use the listFiles() method). The SmbFileInputStream object is only for reading information from a file.
To write a file to a directory, do this...
File file = new File("/mnt/sdcard/filename.txt");
file.mkdirs(); // this creates all the directories that are missing
FileOutputStream os = new FileOutputStream (file);
// now write the file data
os.write(...);
In your code, change the following few lines...
try
{
din=new SmbFileInputStream(src);
dout=new FileOutputStream(Environment.getExternalStorageDirectory()+"/"+src.getName());
int c;
while((c=din.read())!=-1)
To this...
try
{
din=new SmbFileInputStream(src);
File outputFile = new File(Environment.getExternalStorageDirectory()+"/"+src.getName()); // ADDED
outputFile.mkdirs(); // ADDED
dout=new FileOutputStream(outputFile); // CHANGED
int c;
while((c=din.read())!=-1)
Also change the following...
if(src.isFile()){
din=new SmbFileInputStream(src);
//dout=new FileOutputStream(Environment.getExternalStorageDirectory()+"/"+src.getName());// REMOVE THIS LINE
File outputFile = new File(Environment.getExternalStorageDirectory()+"/"+src.getName()); // ADDED
outputFile.mkdirs(); // ADDED
dout=new FileOutputStream(outputFile); // ADDED
}
else {
//din=new SmbFileInputStream(src); // REMOVE THIS LINE
File outputFile = new File(Environment.getExternalStorageDirectory()+"/"+src.getName());
outputFile.mkdirs();
//dout=new FileOutputStream(outputFile); // REMOVE THIS LINE
}
Related
I have below code where i am reading the file from particular directory, processing it and once processed i am moving the file to archive directory. This is working fine. I am receiving new file everyday and i am using Control-M scheduler job to run this process.
Now in next run i am reading the new file from that particularly directory again and checking this file with the file in the archive directory and if the content is different then only process the file else dont do anything. There is shell script written to do this job and we dont see any log for this process.
Now i want to produce log message in my java code if the files are identical from the particular directory and in the archive directory then generate log that 'files are identical'. But i dont know exactly how to do this. I dont want to write the the logic to process or move anything in the file ..i just need to check the files are equal and if it is then
produce log message. The file which i recieve are not very big and the max size can be till 10MB.
Below is my code:
for(Path inputFile : pathsToProcess) {
// read in the file:
readFile(inputFile.toAbsolutePath().toString());
// move the file away into the archive:
Path archiveDir = Paths.get(applicationContext.getEnvironment().getProperty(".archive.dir"));
Files.move(inputFile, archiveDir.resolve(inputFile.getFileName()),StandardCopyOption.REPLACE_EXISTING);
}
return true;
}
private void readFile(String inputFile) throws IOException, FileNotFoundException {
log.info("Import " + inputFile);
try (InputStream is = new FileInputStream(inputFile);
Reader underlyingReader = inputFile.endsWith("gz")
? new InputStreamReader(new GZIPInputStream(is), DEFAULT_CHARSET)
: new InputStreamReader(is, DEFAULT_CHARSET);
BufferedReader reader = new BufferedReader(underlyingReader)) {
if (isPxFile(inputFile)) {
Importer.processField(reader, tablenameFromFilename(inputFile));
} else {
Importer.processFile(reader, tablenameFromFilename(inputFile));
}
}
log.info("Import Complete");
}
}
Based on the limited information about the size of file or performance needs, something like this can be done. This may not be 100% optimized, but just an example. You may also have to do some exception handling in the main method, since the new method might throw an IOException:
import org.apache.commons.io.FileUtils; // Add this import statement at the top
// Moved this statement outside the for loop, as it seems there is no need to fetch the archive directory path multiple times.
Path archiveDir = Paths.get(applicationContext.getEnvironment().getProperty("betl..archive.dir"));
for(Path inputFile : pathsToProcess) {
// Added this code
if(checkIfFileMatches(inputFile, archiveDir); {
// Add the logger here.
}
//Added the else condition, so that if the files do not match, only then you read, process in DB and move the file over to the archive.
else {
// read in the file:
readFile(inputFile.toAbsolutePath().toString());
Files.move(inputFile, archiveDir.resolve(inputFile.getFileName()),StandardCopyOption.REPLACE_EXISTING);
}
}
//Added this method to check if the source file and the target file contents are same.
// This will need an import of the FileUtils class. You may change the approach to use any other utility file, or read the data byte by byte and compare. If the files are very large, probably better to use Buffered file reader.
private boolean checkIfFileMatches(Path sourceFilePath, Path targetDirectoryPath) throws IOException {
if (sourceFilePath != null) { // may not need this check
File sourceFile = sourceFilePath.toFile();
String fileName = sourceFile.getName();
File targetFile = new File(targetDirectoryPath + "/" + fileName);
if (targetFile.exists()) {
return FileUtils.contentEquals(sourceFile, targetFile);
}
}
return false;
}
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;
}
I am trying to move files from one directory to another delete that file from source directory after moving.
for (File file : files) {
if (file != null) {
boolean status = moveFile(file, filePath, name, docGroupId);
if (status) {
//some operations....
}
}
}
public static boolean moveFile(final File file, final String filePath, final String groupName, Integer docGroupId) {
// TODO Auto-generated method stub
String selectedDirectory = filePath + File.separator + groupName;
InputStream in = null;
OutputStream out = null;
try {
if (!file.isDirectory()) {
File dir = new File(selectedDirectory);
if (!dir.exists()) {
dir.mkdirs();
}
String newFilString = dir.getAbsolutePath() +
File.separator + file.getName();
File newFile = new File(newFilString);
in = new FileInputStream(file);
out = new FileOutputStream(newFile);
byte[] moveBuff = new byte[1024];
int butesRead;
while ((butesRead = in.read(moveBuff)) > 0) {
out.write(moveBuff, 0, butesRead);
}
}
in.close();
out.close();
if(file.delete())
return true;
} catch (Exception e) {
return false;
}
}
The program works on Linux-Ubuntu and all files are moved to another directory and deleted from source directory, but in Windows system all files are moved but failed to delete one or two files from source directory. Please note that while debugging the program is working fine.
Consider using Files.delete instead of File.delete. The javadoc says:
Note that the Files class defines the delete method to throw an IOException when a file cannot be deleted. This is useful for error reporting and to diagnose why a file cannot be deleted.
This should provide the information necessary to diagnose the problem.
So, if problem comes with delete, possible explanations:
you do file.delete() on every files and directories. How do you know the directory is empty ? If not, it will fail, then what happen to next instructions ?
file deletion is OS-dependant. On Windows, you can have many security issues, depending on which user, which rights, which location. You should check with a file-delete-alone program;
last: files can be locked by other programs (even explorer), it is also OS-dependant.
You don't need any of this if the source and target are in the same file system. Just use File.renameTo().
I am trying to transfer the data from old textfile to new textfile. Although the code below is able to transfer successfully, it does not delete the old textfile. May I know why is this so?
private void dataTransfer(String oldFilePath, String newFilePath) {
byte[] buffer = new byte[10000];
try {
FileInputStream fileInput = new FileInputStream(oldFilePath);
BufferedInputStream bufferedInput = new BufferedInputStream(fileInput);
FileOutputStream fileOutput = new FileOutputStream(newFilePath);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutput);
while(true) {
int length = fileInput.read(buffer);
if(length == -1) {
break;
} else {
bufferedOutput.write(buffer);
bufferedOutput.flush();
}
}
fileInput.close();
bufferedInput.close();
fileOutput.close();
bufferedOutput.close();
File oldFile = new File(oldFilePath);
oldFile.delete();
} catch (IOException e) {
e.printStackTrace();
System.out.println(ERROR_TRANSFER_DATA);
}
}
Update the JRE and JDK, make sure you have the rights on the file. Try with a file created by you.
Also, add a catch block for SecurityException
For deleting a file it should work fine but for deleting a directory you have to make sure that Directory is Empty.
You can use the following code block. It works, though don't know. Even without setWritable, it works,
oldFile.setWritable(true);
if(!oldFile.delete()){
System.out.println("de;eted");
}
According to Oracle's docs, the delete method does not guarantee that it will delete the file.
http://docs.oracle.com/javase/7/docs/api/java/io/File.html#delete()
Deleting a file will fail if:
file does not exist
there is a lock on that file it might be opened by another process
file does not exist on the disk
you don't have enough permissions to delete that file (in this case a SecurityException is thrown)
I agree with #panagdu that you might not have sufficient rights to delete the file.
Just as a fluke try closing bufferedStream before fileInputStream
like
bufferedInput.close();
fileInput.close();
bufferedOutput.close();
fileOutput.close();
But I don't think this will help.
Test your code for files with sufficient permission. For example Java does not allow the delete() for system files.
I'm attempting to save files to my SD but i cannot get it to, I even tried moving the app to the SD to see if I can. I don't really care where it ends up on there but this isn;t working:
String state = Environment.getExternalStorageState();
File filesDir;
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
filesDir = getExternalFilesDir(null);
Log.i(Utils.TAG, "We can read and write the media: " + filesDir.getAbsolutePath()); // This is the local on the phone
} else {
// Load another directory, probably local memory
filesDir = getFilesDir();
Log.i(Utils.TAG, "Load another directory, probably local memory: " + filesDir.getAbsolutePath());
}
try {
// Creates a trace file in the primary external storage space of the
// current application.
// If the file does not exists, it is created.
//File traceFile = new File(((Context)this).getExternalFilesDir(null), "TraceFile.txt"); //This one saves to the internal file folder
File traceFile = new File(filesDir, "TraceFile.txt");
Log.i(Utils.TAG, traceFile.getAbsolutePath());
if (!traceFile.exists())
traceFile.createNewFile();
// Adds a line to the trace file
BufferedWriter writer = new BufferedWriter(new FileWriter(traceFile, true /*append*/));
writer.write("This is a test trace file.");
writer.close();
// Refresh the data so it can seen when the device is plugged in a
// computer. You may have to unplug and replug the device to see the
// latest changes. This is not necessary if the user should not modify
// the files.
MediaScannerConnection.scanFile((Context)(this),
new String[] { traceFile.toString() },
null,
null);
} catch (IOException e) {
Log.i(Utils.TAG, "Unable to write to the TraceFile.txt file.");
}
However, this gave me the SD file but I couldn't write to it:
public HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
}
Android 4.4+ allows you to write to removable media, but only in select spots obtained by methods like:
getExternalFilesDirs()
getExternalCacheDirs()
getExternalMediaDirs() (this one was added in Android 5.0 IIRC)
Note the plural on those method names. If they return 2+ entries, the second and subsequent ones should be on removable media, in a directory that is unique for your app. You can read and write to those directories without any <uses-permission> element.
You might also consider the Storage Access Framework (ACTION_OPEN_DOCUMENT and kin), to allow the user to choose where to place the file, whether that be on external storage or removable storage or Google Drive or whatever.
Android 4.4 implemented numerous SD card limits, and there were (and still are) a lot of apps which broke during this period, because of issues with write limitations to the SD card. Your code itself seems fine to me, but my believe is that it's Android 4.4's SD Card limits which ensure that it doesn't work. How to fix that (without root access) is beyond me.