I have developed a application in which user select the particular folder and it counts all the java files in that folder plus the line of code individually in those files and show at console but in a java project there are so many packages and right now I have to navigate until a particular package , I want to modify the application in such a way that when user select the particular project, he will then further navigate to only src folder and from src folder all the packages containing java files line of code will be counted.
public class abc {
/**
* #param args
* #throws FileNotFoundException
*/
private static int totalLineCount = 0;
private static int totalFileScannedCount = 0;
public static void main(String[] args) throws FileNotFoundException {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("C:" + File.separator));
chooser.setDialogTitle("FILES ALONG WITH LINE NUMBERS");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
Map<String, Integer> result = new HashMap<String, Integer>();
File directory = new File(chooser.getSelectedFile().getAbsolutePath());
List<File> files = getFileListing(directory);
//print out all file names, in the the order of File.compareTo()
for (File file : files) {
System.out.println("Directory: "+file);
result = getFileLineCount(file);
totalFileScannedCount += result.size();
}
System.out.println("*****************************************");
System.out.println("FILE NAME FOLLOWED BY LOC");
System.out.println("*****************************************");
for (Map.Entry<String, Integer> entry : result.entrySet()) {
System.out.println(entry.getKey() + " ==> " + entry.getValue());
}
System.out.println("*****************************************");
System.out.println("SUM OF FILES SCANNED ==>" + "\t" + totalFileScannedCount);
System.out.println("SUM OF ALL THE LINES ==>" + "\t" + totalLineCount);
}
}
public static Map<String, Integer> getFileLineCount(File directory) throws FileNotFoundException {
Map<String, Integer> result = new HashMap<String, Integer>();
File[] files = directory.listFiles(new FilenameFilter() {
#Override
public boolean accept(File directory, String name) {
if (name.endsWith(".java")) {
return true;
} else {
return false;
}
}
});
for (File file : files) {
if (file.isFile()) {
Scanner scanner = new Scanner(new FileReader(file));
int lineCount = 0;
try {
for (lineCount = 0; scanner.nextLine() != null; lineCount++);
} catch (NoSuchElementException e) {
result.put(file.getName(), lineCount);
totalLineCount += lineCount;
}
}
}
return result;
}
/**
* Recursively walk a directory tree and return a List of all
* Files found; the List is sorted using File.compareTo().
*
* #param aStartingDir is a valid directory, which can be read.
*/
static public List<File> getFileListing(
File aStartingDir) throws FileNotFoundException {
validateDirectory(aStartingDir);
List<File> result = getFileListingNoSort(aStartingDir);
Collections.sort(result);
return result;
}
// PRIVATE //
static private List<File> getFileListingNoSort(
File aStartingDir) throws FileNotFoundException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = aStartingDir.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for (File file : filesDirs) {
if(file.isDirectory()) {
result.add(file);
}
if (!file.isFile()) {
//must be a directory
//recursive call!
List<File> deeperList = getFileListingNoSort(file);
result.addAll(deeperList);
}
}
return result;
}
/**
* Directory is valid if it exists, does not represent a file, and can be read.
*/
static private void validateDirectory(
File aDirectory) throws FileNotFoundException {
if (aDirectory == null) {
throw new IllegalArgumentException("Directory should not be null.");
}
if (!aDirectory.exists()) {
throw new FileNotFoundException("Directory does not exist: " + aDirectory);
}
if (!aDirectory.isDirectory()) {
throw new IllegalArgumentException("Is not a directory: " + aDirectory);
}
if (!aDirectory.canRead()) {
throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
}
}
}
Now the problem is the issue with this approach is that if in java project named TESTRESULT there are 3 packages and each package having 2 files each then in the result on console it shows file name followed by loc of only the latest package only lets say in a java projest 3 packages named abc, def and tyu
com.abc package having files --->abc.java
com.def package having files --->abc.java
com.tyu package having files --->FileBrowse.java , FileCountLine.java
the outcome shown in console is...
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\.settings
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\bin
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\src
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\src\com
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\src\com\abc
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\src\com\def
Directory: C:\Users\vaio\Desktop\Demo\TESTRESULT\src\tyu
*****************************************
FILE NAME FOLLOWED BY LOC
*****************************************
FileBrowse.java ==> 95
FileCountLine.java ==> 53
*****************************************
SUM OF FILES SCANNED ==> 4
SUM OF ALL THE LINES ==> 296
which is not perfect. please advise HOW IT WILL SHOW FILENAME FOLLOWED BY LOC for all the files
What I think is In the method that reads the files and the line count, you create a NEW Map for each directory and re-assign it to the same result. Since you do not display the data before you re-assign the Map, the previous Map is no longer accessible and by the time you get to the display you only have a Map for the last directory. Instead, you should maintain a single Map and insert new values from each directory into the same Map.
public static void main(String[] args) throws FileNotFoundException {
//...
for (File file : files) {
System.out.println("Directory: "+file);
result = getFileLineCount(file);
Right there you get a Map back from getFileLineCount(), and assign it to result. This discards the previously created result Map, and you lose everything that was already there. You have a few options:
Pass the result Map into the getFileLineCount() method so you can add results to the one Map, rather than creating a new Map for each folder inside the getFileLineCount() method
Take the results from getLineCount() and copy them into the result Map rather than replacing the result Map
Create another collection, like a Map like: Map<String, Map<String, Integer>> (which would map the results returned by the getFileLineCount() method to the name of the directory those results pertain to), or List<Map<String, Integer>> (which would be a simple list of the results returned by getFileLineCount() without any mapping to the parent directory).
Please advise how to refactor my code ,Thanks in advance
You could do something like this:
result.put(file, lineCount);
instead of
result.put(file.getName(), lineCount);
And when you print the result you could print the pretty file name. Like this:
for (Map.Entry<File, Integer> entry : result.entrySet()) {
System.out.println(entry.getKey().getName() + " ==> " + entry.getValue());
}
Of course map should be then declared as: Map.Entry<File, Integer>
Of course this can be improved a lot but with minimal changes you could have this (that is actually doing what you expect, please just change to print the name if you don't want the entire path):
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Scanner;
import javax.swing.JFileChooser;
public class abc {
/**
* #param args
* #throws FileNotFoundException
*/
private static int totalLineCount = 0;
private static int totalFileScannedCount = 0;
public static void main(final String[] args) throws FileNotFoundException {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("C:" + File.separator));
chooser.setDialogTitle("FILES ALONG WITH LINE NUMBERS");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
Map<File, Integer> result = new HashMap<File, Integer>();
File directory = new File(chooser.getSelectedFile().getAbsolutePath());
List<File> files = getFileListing(directory);
// print out all file names, in the the order of File.compareTo()
for (File file : files) {
System.out.println("Directory: " + file);
getFileLineCount(result, file);
}
System.out.println("*****************************************");
System.out.println("FILE NAME FOLLOWED BY LOC");
System.out.println("*****************************************");
for (Map.Entry<File, Integer> entry : result.entrySet()) {
System.out.println(entry.getKey().getAbsolutePath() + " ==> " + entry.getValue());
}
System.out.println("*****************************************");
System.out.println("SUM OF FILES SCANNED ==>" + "\t" + totalFileScannedCount);
System.out.println("SUM OF ALL THE LINES ==>" + "\t" + totalLineCount);
}
}
public static void getFileLineCount(final Map<File, Integer> result, final File directory)
throws FileNotFoundException {
File[] files = directory.listFiles(new FilenameFilter() {
public boolean accept(final File directory, final String name) {
if (name.endsWith(".java")) {
return true;
} else {
return false;
}
}
});
for (File file : files) {
if (file.isFile()) {
totalFileScannedCount++;
Scanner scanner = new Scanner(new FileReader(file));
int lineCount = 0;
try {
for (lineCount = 0; scanner.nextLine() != null; lineCount++) {
;
}
} catch (NoSuchElementException e) {
result.put(file, lineCount);
totalLineCount += lineCount;
}
}
}
}
/**
* Recursively walk a directory tree and return a List of all Files found;
* the List is sorted using File.compareTo().
*
* #param aStartingDir
* is a valid directory, which can be read.
*/
static public List<File> getFileListing(final File aStartingDir) throws FileNotFoundException {
validateDirectory(aStartingDir);
List<File> result = getFileListingNoSort(aStartingDir);
Collections.sort(result);
return result;
}
// PRIVATE //
static private List<File> getFileListingNoSort(final File aStartingDir) throws FileNotFoundException {
List<File> result = new ArrayList<File>();
File[] filesAndDirs = aStartingDir.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for (File file : filesDirs) {
if (file.isDirectory()) {
result.add(file);
}
if (!file.isFile()) {
// must be a directory
// recursive call!
List<File> deeperList = getFileListingNoSort(file);
result.addAll(deeperList);
}
}
return result;
}
/**
* Directory is valid if it exists, does not represent a file, and can be
* read.
*/
static private void validateDirectory(final File aDirectory) throws FileNotFoundException {
if (aDirectory == null) {
throw new IllegalArgumentException("Directory should not be null.");
}
if (!aDirectory.exists()) {
throw new FileNotFoundException("Directory does not exist: " + aDirectory);
}
if (!aDirectory.isDirectory()) {
throw new IllegalArgumentException("Is not a directory: " + aDirectory);
}
if (!aDirectory.canRead()) {
throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
}
}
}
Related
I want to read all files recursive inside a given path and show the path and Byte size in the output of every single File.
public class ReadFilesInPathRecursion {
public void listFiles (String startDir) {
File dir = new File(startDir);
File[] files = dir.listFiles();
if (files!=null && files.length >= 0) {
for(File file : files) {
if(file.isDirectory()) {
listFiles(file.getAbsolutePath()); // Recursion (absolute)
} else {
System.out.println(file.getName() + " (size in bytes: " + file.length() + ") " + "(path: " + file.getAbsoluteFile() + ")");
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ReadFilesInPathRecursion test = new ReadFilesInPathRecursion();
String startDir = sc.next();
test.listFiles(startDir);
}
Here I have code for displaying metadata for 1 file. I wanted to know how can I use to display metadata for a specified directory?
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import javax.imageio.metadata.*;
import java.util.Scanner;
public class Metadata{
public static void main(String[] args) {
Metadata meta = new Metadata();
if (new File("./images/test.jpg").exists()) {
System.out.println("Can find " + "test.jpg file");
meta.readAndDisplayMetadata("test.jpg");
} else {
System.out.println("cannot find file: " + "test.jpg");
}
}
void readAndDisplayMetadata(String fileName ) {//or String fileName
try {
File file = new File(fileName);
ImageInputStream iis = ImageIO.createImageInputStream(file);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
if (readers.hasNext()) {
// pick the first available ImageReader
ImageReader reader = readers.next();
// attach source to the reader
reader.setInput(iis, true);
// read metadata of first image
IIOMetadata metadata = reader.getImageMetadata(0);
String[] names = metadata.getMetadataFormatNames();
int length = names.length;
for (int i = 0; i < length; i++) {
System.out.println( "Format name: " + names[ i ] );
displayMetadata(metadata.getAsTree(names[i]));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
void displayMetadata(Node root) {
displayMetadata(root, 0);
}
void indent(int level) {
for (int i = 0; i < level; i++)
System.out.print(" ");
}
void displayMetadata(Node node, int level) {
// print open tag of element
indent(level);
System.out.print("<" + node.getNodeName());
NamedNodeMap map = node.getAttributes();
if (map != null) {
// print attribute values
int length = map.getLength();
for (int i = 0; i < length; i++) {
Node attr = map.item(i);
System.out.print(" " + attr.getNodeName() +
"=\"" + attr.getNodeValue() + "\"");
}
}
Node child = node.getFirstChild();
if (child == null) {
// no children, so close element and return
System.out.println("/>");
return;
}
// children, so close current tag
System.out.println(">");
while (child != null) {
// print children recursively
displayMetadata(child, level + 1);
child = child.getNextSibling();
}
// print close tag of element
indent(level);
System.out.println("</" + node.getNodeName() + ">");
}
}
I have used DirectoryPath but sadly ImageInputStream has no interface for directories.
Are there any libraries or frameworks that are available that can automatically give image metadata for a directory as JSON?
Given that you already have code to displaying metadata for a single file, it's trivial to modify it to support multiple files.
All you need is the isDirectory() and listFiles() methods of File (or, if you are on Java 8+, you can use the Files.list(Path) method, for lazy iteration*).
If your input file is a directory, list each file and recurse:
public class Metadata {
public static void main(String[] args) {
Metadata meta = new Metadata();
File file = new File(args[0]);
if (file.exists()) {
System.out.println("Can find " + file);
meta.readAndDisplayMetadata(file);
}
else {
System.out.println("cannot find file: " + file);
}
}
void readAndDisplayMetadata(File file) {
// If you *don't* want recursive behavior,
// move this block "outside" or to a separate method
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
readAndDisplayMetadata(f);
}
}
// Rest of method as is...
}
}
*) The below is better, if you can use it, as the above can run out of memory if you have many files in the directory.
void readAndDisplayMetadata(File file) throws IOException {
Path path = file.toPath();
if (Files.isDirectory(path /* optional, handle symbolic links */)) {
Files.list(path)
.forEach(p -> readAndDisplayMetadata(p.toFile()));
}
// Rest of method as is...
}
Ok, so I have a folder with about 2000 pictures, all with weird names, I would like to loop through the whole thing, and rename them to "something" + the number(i in the for loop). Is there anyway to rename a file when you only know the place in the directory and not the name. I guess the main problem is getting the name of the file at index x in a directory, is there anyway to do this?
public class stuff {
static ArrayList<File> images = new ArrayList<>();
public static void main(String[] args) throws IOException{
Files.walk(Paths.get("C:\\Users\\Seth Gower\\Pictures\\Stuff for imgur\\iFunny Dumps\\iFunny Dump (All)"))
.forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
images.add(new File(filePath.toString()));
}
});
for(File x : images)
System.out.println(x.getName());
for (int i = 0; i < images.size(); i ++){
System.out.println(images.get(i).renameTo(new File(
"C:\\Users\\Seth Gower\\Pictures\\Stuff for imgur\\iFunny Dumps\\iFunny Dump (All)" + "\\" + "ifunnyDump" + i)));
}
}
}
static ArrayList<File> images = new ArrayList<>();
public static void main(String[] args) throws IOException{
Files.walk(Paths.get("path")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
images.add(new File(filePath.toString()));
}
});
for (int i = 0; i < images.size(); i ++){
images.get(i).renameTo(new File("path" + "\\" + "text" + i + ".jpg"));
}
}
This worked, thanks to #hexafraction and #MatthewStrawbridge
This is really simple
you need to first find the directory your files are located in
File dir = new File("C:\\yourdirectory");
now you need to loop through every file in the directory an rename it. A for each loop would be best. If you want before the loop you can check if the directory you specified is really a directory with
if (dir.isDirectory())
int i = 0;
for (File f : dir.listFiles()) {
try {
f.renameTo("YourText_"+i+".jpg");
i++;
}
catch (Exception e)
{
System.out.println(e);
}
}
I have several files, thing is that i need to know which one was the last created according to the numbers I give them automatically.
For example if i have: file1, file2, file3 I want to receive the file3. I can't do this with "last modified" because I have other folders and files in the same directory.
Also to this last file I would like to increment his number in 1.
Put the files in a list and sort it lexically, then take the last one.
Ofcourse you have to filter out the ones you are looking for with regex or contains/startswith/endswith
Here is an alternate simple solution.
import java.io.File;
public class FileUtility {
private static final String FOLDER_PAHT = "D:\\Test";
private static final String FILE_PREFIX = "file";
/**
* #param args
*/
public static void main(String[] args) {
int lastFileNumber = getLastFileNumber();
System.out.println("In folder " + FOLDER_PAHT + " last file is " + FILE_PREFIX + lastFileNumber);
if(incrementFileNumber(lastFileNumber)) {
System.out.println("After incrementing the last file becomes : FILE_PREFIX" + lastFileNumber + 1);
} else {
System.out.println("Some error occured while updating file number.");
}
}
private static int getLastFileNumber(){
int maxFileNumber = 0;
File folder = new File(FOLDER_PAHT);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
String fileName = listOfFiles[i].getName();
if (listOfFiles[i].isFile() && fileName.contains(FILE_PREFIX)) {
try {
int fileNumber = Integer.parseInt(fileName.substring(FILE_PREFIX.length(), fileName.indexOf(".")));
if(maxFileNumber < fileNumber) {
maxFileNumber = fileNumber;
}
} catch (NumberFormatException e) {
// Because there can be files with starting name as FILE_PREFIX but not valid integer appended to them.
//NOthing to do
}
}
}
return maxFileNumber;
}
private static boolean incrementFileNumber(final int oldNumber) {
File oldfile =new File(FOLDER_PAHT + File.separator + FILE_PREFIX + oldNumber);
File newfile =new File(FOLDER_PAHT + File.separator + FILE_PREFIX + (oldNumber + 1) + ".txt");
return oldfile.renameTo(newfile);
}
}
public static void main (String[] args) throws Exception
{
File foldersContainer = new File("c:/test");
String latestFileName = "";
Integer highestFileNumber = 0;
for (File tmpFile : foldersContainer.listFiles()){
if (tmpFile.isFolder()) {
int currentNumber = extractFileNumber(tmpFile.getName());
if (currentNumber > highestFileNumber){
highestFileNumber = currentNumber;
latestFileName = tmpFile.getName();
}
}
}
latestFileName.replace(highestFileNumber.toString(),
(++highestFileNumber).toString());
System.out.println("Latest file (incremented): " + latestFileName);
}
private static int extractFileNumber(String name){
for (int x=name.length()-1; x >= 0; x--)
if (!Character.isDigit(name.charAt(x)))
return Integer.parseInt(name.substring(x+1));
return -1;
}
If the filename before the last number can contain numbers, then you should use lastIndexOf to be sure of finding only the occurrence you really want to increment.
instead of
latestFileName.replace(highestFileNumber.toString(),
(++highestFileNumber).toString());
you should use
latestFileName = latestFileName
.substring(0,latestFileName.lastIndexOf(highestFileNumber.toString()))
.concat((++highestFileNumber).toString());
Ok, here's an alternative. I'm assuming that the file name is known and they have the same name.
public static void main(String[] args) {
File dir = new File("directory of the files");
File [] files = dir.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.startsWith("folder");
}
});
for (File file : files) {
System.out.println(file.getName());
}
System.out.println("---------");
List<File> myFile = new ArrayList<>(Arrays.asList(files));
Collections.sort(myFile, new Comparator<File>() {
#Override
public int compare(File f1, File f2) {
// TODO Auto-generated method stub
int numberF1 = Integer.parseInt(f1.getName().replace("folder",""));
int numberF2 = Integer.parseInt(f2.getName().replace("folder",""));
return Integer.compare(numberF1, numberF2);
}
});
for (File file : myFile) {
System.out.println(file.getName());
}
}
Output :
folder10
folder2
folder20
folder250
---------
folder2
folder10
folder20
folder250
I want to transfer a folder and a subfolder using JSch ChannelSftp. I can successfully transfer files using channelsftp.put(src, dest) command but this does not work for folders (at least I could not make it work). So can someone please explain how can I transfer folders and subfolders using ChannelSftp?
To work with multilevel folder structures in jsch you:
enter them;
list their contents;
do smth with every found item;
repeat 1, 2 & 3 if subfolder is found.
DOWNLOAD dirs method inside your JSCH class:
public void downloadDir(String sourcePath, String destPath) throws SftpException { // With subfolders and all files.
// Create local folders if absent.
try {
new File(destPath).mkdirs();
} catch (Exception e) {
System.out.println("Error at : " + destPath);
}
sftpChannel.lcd(destPath);
// Copy remote folders one by one.
lsFolderCopy(sourcePath, destPath); // Separated because loops itself inside for subfolders.
}
private void lsFolderCopy(String sourcePath, String destPath) throws SftpException { // List source (remote, sftp) directory and create a local copy of it - method for every single directory.
Vector<ChannelSftp.LsEntry> list = sftpChannel.ls(sourcePath); // List source directory structure.
for (ChannelSftp.LsEntry oListItem : list) { // Iterate objects in the list to get file/folder names.
if (!oListItem.getAttrs().isDir()) { // If it is a file (not a directory).
if (!(new File(destPath + "/" + oListItem.getFilename())).exists() || (oListItem.getAttrs().getMTime() > Long.valueOf(new File(destPath + "/" + oListItem.getFilename()).lastModified() / (long) 1000).intValue())) { // Download only if changed later.
new File(destPath + "/" + oListItem.getFilename());
sftpChannel.get(sourcePath + "/" + oListItem.getFilename(), destPath + "/" + oListItem.getFilename()); // Grab file from source ([source filename], [destination filename]).
}
} else if (!(".".equals(oListItem.getFilename()) || "..".equals(oListItem.getFilename()))) {
new File(destPath + "/" + oListItem.getFilename()).mkdirs(); // Empty folder copy.
lsFolderCopy(sourcePath + "/" + oListItem.getFilename(), destPath + "/" + oListItem.getFilename()); // Enter found folder on server to read its contents and create locally.
}
}
}
REMOVE dirs method inside your JSCH class:
try {
sftpChannel.cd(dir);
Vector<ChannelSftp.LsEntry> list = sftpChannel.ls(dir); // List source directory structure.
for (ChannelSftp.LsEntry oListItem : list) { // Iterate objects in the list to get file/folder names.
if (!oListItem.getAttrs().isDir()) { // If it is a file (not a directory).
sftpChannel.rm(dir + "/" + oListItem.getFilename()); // Remove file.
} else if (!(".".equals(oListItem.getFilename()) || "..".equals(oListItem.getFilename()))) { // If it is a subdir.
try {
sftpChannel.rmdir(dir + "/" + oListItem.getFilename()); // Try removing subdir.
} catch (Exception e) { // If subdir is not empty and error occurs.
lsFolderRemove(dir + "/" + oListItem.getFilename()); // Do lsFolderRemove on this subdir to enter it and clear its contents.
}
}
}
sftpChannel.rmdir(dir); // Finally remove the required dir.
} catch (SftpException sftpException) {
System.out.println("Removing " + dir + " failed. It may be already deleted.");
}
CALL these methods from outside like:
MyJSCHClass sftp = new MyJSCHClass();
sftp.removeDir("/mypublic/myfolders");
sftp.disconnect(); // Disconnecting is obligatory - otherwise changes on server can be discarded (e.g. loaded folder disappears).
Above code(by zon) works for download as per my understanding.I need to upload to a remote server.I wrote below code to achieve the same.Please try and comment if any issue(it ignores files starting with ".")
private static void lsFolderCopy(String sourcePath, String destPath,
ChannelSftp sftpChannel) throws SftpException, FileNotFoundException {
File localFile = new File(sourcePath);
if(localFile.isFile())
{
//copy if it is a file
sftpChannel.cd(destPath);
if(!localFile.getName().startsWith("."))
sftpChannel.put(new FileInputStream(localFile), localFile.getName(),ChannelSftp.OVERWRITE);
}
else{
System.out.println("inside else "+localFile.getName());
File[] files = localFile.listFiles();
if(files!=null && files.length > 0 && !localFile.getName().startsWith("."))
{
sftpChannel.cd(destPath);
SftpATTRS attrs = null;
//check if the directory is already existing
try {
attrs = sftpChannel.stat(destPath+"/"+localFile.getName());
} catch (Exception e) {
System.out.println(destPath+"/"+localFile.getName()+" not found");
}
//else create a directory
if (attrs != null) {
System.out.println("Directory exists IsDir="+attrs.isDir());
} else {
System.out.println("Creating dir "+localFile.getName());
sftpChannel.mkdir(localFile.getName());
}
//System.out.println("length " + files.length);
for(int i =0;i<files.length;i++)
{
lsFolderCopy(files[i].getAbsolutePath(),destPath+"/"+localFile.getName(),sftpChannel);
}
}
}
}
From: http://the-project.net16.net/Projekte/projekte/Projekte/Programmieren/sftp-synchronisierung.html
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Vector;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpException;
public class FileMaster {
public boolean FileAction;
public File local;
public String serverDir;
public ChannelSftp channel;
public FileMaster(boolean copyOrDelete, File local, String to, ChannelSftp channel){
this.FileAction = copyOrDelete;
this.local = local;
this.serverDir = to;
this.channel = channel;
}
/*
* If FileAction = true, the File local is copied to the serverDir, else the file is deleted.
*/
public void runMaster() throws FileNotFoundException, SftpException{
if(FileAction){
copy(local, serverDir, channel);
} else {
delete(serverDir, channel);
}
}
/*
* Copies recursive
*/
public static void copy(File localFile, String destPath, ChannelSftp clientChannel) throws SftpException, FileNotFoundException{
if(localFile.isDirectory()){
clientChannel.mkdir(localFile.getName());
GUI.addToConsole("Created Folder: " + localFile.getName() + " in " + destPath);
destPath = destPath + "/" + localFile.getName();
clientChannel.cd(destPath);
for(File file: localFile.listFiles()){
copy(file, destPath, clientChannel);
}
clientChannel.cd(destPath.substring(0, destPath.lastIndexOf('/')));
} else {
GUI.addToConsole("Copying File: " + localFile.getName() + " to " + destPath);
clientChannel.put(new FileInputStream(localFile), localFile.getName(),ChannelSftp.OVERWRITE);
}
}
/*
* File/Folder is deleted, but not recursive
*/
public void delete(String filename, ChannelSftp sFTPchannel) throws SftpException{
if(sFTPchannel.stat(filename).isDir()){
#SuppressWarnings("unchecked")
Vector<LsEntry> fileList = sFTPchannel.ls(filename);
sFTPchannel.cd(filename);
int size = fileList.size();
for(int i = 0; i < size; i++){
if(!fileList.get(i).getFilename().startsWith(".")){
delete(fileList.get(i).getFilename(), sFTPchannel);
}
}
sFTPchannel.cd("..");
sFTPchannel.rmdir(filename);
} else {
sFTPchannel.rm(filename.toString());
}
GUI.addToConsole("Deleted: " + filename + " in " + sFTPchannel.pwd());
}
}