1. Approach

Java knows two approaches of file access:

  • The traditional java.io.File

  • The newer java.nio.file.* with some enhancements and benefits.

The second one does better separate the file handling from the underlying operation system, gives more flexibility. But the same problem is given:

Accessing a file may need a while till the access is finished. If this access runs in a graphical event thread, then the graphic my hang if the file access needs more time for example because of access in network or longer file operations. Then the user cannot press an 'abort' button or such one. Hence, it is better to delegate the handling with the underlying file system in another thread and works with callback operations.

The second approach is: What about a quasi file access to embedded hardware, with a small file system non standard accessible, for example only via special serial interface access? It is too complicated to write the proper driver using the java.nio.file.* system. As alternative the interface org.vishia.fileRemote.FileRemoteAccessor is offered to implement, with lesser but maybe sufficient operations.

2. One FileRemote instance per physical file as twin for access in the application.

is inherited from java.io.File. The basic idea behind this is, offer the same operation as the familiar File instance. But the implementation does not follow java.io.File (this was the first idea), instead the newer java.nio.files package is used, for the implementation to the local file system of a PC platform. This is implemented in

2.1. FileCluster

The relation between a FileRemote instance and the physical file in the whole application should be unique. That prevents too much file system accesses for refresh (which may be important with slow network access to an embedded hardware). And also some marking operations on file can be done which should be unique. The file is presented by its path, and this path is associated to one FileRemote instance.

To fulfill this approach, an only one instance of org.vishia.fileRemote.Cluster for the whole application contains all used directory paths with a list of members and the associated FileRemote instance. Getting a FileRemote instance is only possible using the cluster. For that the association FileRemote.clusterOfApplication refers the singleton instance.

2.2. FileRemoteAccessor

The interface org.vishia.fileRemote.FileRemoteAccessor is referred by any FileRemote instance in FileRemote.device. All FileRemote instances of the same root path have the same device, but any refers it for itself. They may specific pathes which refers another device, especially for embedded hardware.

The implementation of the FileRemoteAccessor for the standard platform of Java uses the

which uses most of features of the java.nio.files.

2.3. Create or get a FileRemote instance

The constructor of this class is protected, hence only internally accessible. A FileRemote instance can only exist with and in its FileCluster. But the FileCluster is a singleton, for your application: FileRemote#clusterOfApplication. Hence it is simple to handle.

Java: Create or get a FileRemote.get(path)
  FileRemote fX       = FileRemote.get("D:/path/to/file.ext");
  FileRemote dirX     = FileRemote.get("D:/path/to/dir/");
  FileRemote dirY     = FileRemote.get("D:/path/to/existingDir");
  FileRemote fLocal   = FileRemote.get("localPath/to/file");
  FileRemote tempfile = FileRemote.get("/tmp/specificTmpPath/file.ext");
  FileRemote homefile = FileRemote.get("~/pathInHome/file.ext");
  FileRemote fY       = FileRemote.get("$ENV/path/$FILE.$EXT");
  • Backslashs are also possible, will be converted to slash

  • Non normalized paths such as "path/../paralleldir/file" are possible, will be normalized.

  • A Slash on end creates an directory, if it is a new directory path. If a directory exists aready, the slash on end is not necessary but possible.

  • A relative path will be completed as absolute one by the content of System.getProperty("user.dir") and not of the content of the operation system’s current dir. But this is the OS current dir, if the System.setProperty("user.dir", newDir) was not changed. Changing the current dir should be possible as part of the application.

  • The "/tmp/" comes original from Linux applications, it is mapped to Windows also using the TMP environment variable.

  • Also the "~/" for the home directory can be used.

  • Environment variables are replaced.

Replacements of environment variables and non absolute or specific paths are processed by ../../docuSrcJava_vishiaBase/org/vishia/util/FileFunctions.html#absolutePath-java.lang.String-java.io.File-

It is important that you get anyway the same instance of FileRemote with the same (normalized) Path in your application because it is all based on the FileCluster. This is important especially marking for marking. FileRemote#setMarked(mask)

Java: Create or get a FileRemote from File
  File fileX = new File("D:/path/to/file");
  FileRemote fX = FileRemote.fromFile(fileX);

That regards the statically known FileCluster and returns a maybe existing instance for this path. The java.io.File is only the information about the path, and fulfills compatibility with File.

To create a FileRemote instance you can use

  • {@link #fromFile(File)} if you have already given a java.io.File instance.

  • {@link #get(String)} with relative or absolute given path.

  • {@link #getDir(CharSequence)} explicitely get or create a directory

  • {@link #getFile(CharSequence, CharSequence)} in opposite to get(String) with dispersed directory path and name

  • {@link #child(CharSequence)} from a given FileRemote as directory

  • {@link #child(CharSequence, int, int, long, long, long)} to create a child with partially known properties

  • {@link #subdir(CharSequence)} to get or create definitely a directory inside a given FileRemote directory.

All these operations do not access the real file system. Instead they search in the {@link #clusterOfApplication} whether the file is already known and returns it, or they create and register the adequate FileRemote instance in the cluster. The FileRemote instance should/can be synchronized with the real file instance by calling {@link #refreshProperties(CallbackEvent)} or for directory instances with {@link #refreshPropertiesAndChildren()}

from the local file system you can call {@link #fromFile(File)}. This delegates working to {@link #fromFile(FileCluster, File)} with the static given {@link #clusterOfApplication} which looks whether the FileRemote instance is existing already, or registeres it in the file cluster. The implementor of the file system depends on the given path.

You can create a child of an existing file by given FileRemote directory instance using {@link #child(CharSequence)}, {@link #subdir(CharSequence)} or {@link #child(CharSequence, int, int, long, long, long)} whereby the child can be a deeper one, the path is a relative path from the given parent. This FileRemote instance describes a possible existing file or maybe a non existing one, adequate like creation of instance of {@link java.io.File}. Note that on {@link #refreshPropertiesAndChildren(CallbackEvent)} this instance will be removed from the children list if it is not existing.

You can get any FileRemote instance with any absolute path calling {@link FileCluster#getFile(CharSequence)}. This instance will be created if it is not existing, or it will be get from an existing instance of this RemoteFile inside the cluster. The instance won’t be deleted if the physical file is not existing. For example you can create

FileRemote testFile = theFileCluster.getFile("X:/MyPath/file.ext");

This instance is existing independent of the existence of such a physical file. But

if(testFile.exists()){....

may return false.

2.4. path in FileRemote

org.vishia.fileRemote.FileRemote#path is the java.nio.file.Path reference of the file. It is public final, so you can access it immediately. This is new since 2023-01. It substantiates usage of java.nio.file.

The public variable path hides the variable with the same name and usual the toString() representation of the super class java.nio.File. This is not a problem for usage, only a little bit confusing on debugging. But the name path is concisely recommended to use.

2.5. java.nio.file.FileSystem and FileStore, different devices

You can simple ask whether your files are stored on the same physical device or get information about:

Java: Quest of physical device:
    FileRemote fsrc = FileRemote.get("q:\\VIDEOS\\telgRingCommAnimation.gif.gif");
    FileRemote fdst = FileRemote.get("T:/telgRingCommAnimation.gif");
    try {
      java.nio.file.FileStore fstore5rc = java.nio.file.Files.getFileStore(fsrc.path);
      java.nio.file.FileStore fstoreDst = java.nio.file.Files.getFileStore(fdst.path);
      test.expect(fstore5rc != fstoreDst, 4, "different phyisical devices for %s... and %s...", fsrc.getAbsolutePath().substring(0,8), fdst.getAbsolutePath().substring(0,8));
    } catch (IOException exc) {
      test.exception(exc);
    }

Here a network drive is used in the path, T: is a RamDisk.

The detection of the same or another file store or file device is used for FileRemote#copyTo(dst, …​): On the same physical device the fast internal java.nio.file.Files.copyTo(…​) is used, without the possibility to get messages about yet copied and still to copy bytes. This is executed immediately on a device in the network. Whereas if two files are on different devices, they should copied by elaborate read and write of byte streams anyway. Hence there are copied by OpenStream etc. with possibility of give feedback and abort on very long files. See chapter Copy in a network location in the same device

The java.nio.file.FileSystem is the same for both files, because both are managed by the underlying Windows file system. Do not confuse the file system with the file device!

Java: Quest of physical device:
    java.nio.file.FileSystem fsSrc = fsrc.path.getFileSystem();
    java.nio.file.FileSystem fsDst = fsrc.path.getFileSystem();
    test.expect(fsSrc == fsDst, 4, "same file systems for %s... and %s...", fsrc.getAbsolutePath().substring(0,8), fdst.getAbsolutePath().substring(0,8));
    Iterable<java.nio.file.FileStore> fstoresSrc = fsSrc.getFileStores();
    for(java.nio.file.FileStore fstoreSrc: fstoresSrc) {
      info(fstoreSrc.toString());
    }
    Iterable<java.nio.file.FileStore> fstoresDst = fsSrc.getFileStores();
    for(java.nio.file.FileStore fstoreDst: fstoresDst) {
      info(fstoreDst.toString());
    }

The output lists the file stores on the file systems. Both are equal and shows associated network devices.

look on the output for this test:

TestFileRemote
test_checkPhysicalDevice
  ok: different phyisical devices for q:/VIDEO... and T:/telgR...
  ok: same file systems for q:/VIDEO... and T:/telgR...
Windows (C:)
Windows (D:)
Windows (G:)
Windows (P:)
Data (Q:)
RAMDisk (T:)
Windows (U:)

3. Some hints to copy and move of java.nio.file.Files

That are hints not only for FileRemote, and partially not only for java.nio.files but generally effects.

3.1. Copy in a network location in the same device

I have tested to copy a very long file (60 MByte) in a network location. Copying this file to another location which needs transport of data via network needs ~ 10 seconds. This is true, of course, because my WLAN has maximal 56 MBit/s. But if I copy this file with java.nio.file.Files.copyTo(…​) for a remote location, but both files are in the same remote location, copying needs only less than one second for 60 MByte! This is surprising, isn’t it? It is not surprising! Because optimization is anytime and everywhere. Developer of operation systems (in this case Windows-10) and system routines to use it think about optimization. The copy process is executed only on the remote computer, by the file drivers, using cache mechanism. The java.nio.file.Files.copyTo(…​) use this operation system capability.

If you organizes the copy by yourself by opening the source file for read, create or open the destination file for write, read and write bytes, then you transport the bytes via network because the access cannot be optimized. read and write are different actions. If you use the java.nio.file.Files.copyTo(…​), the implementation does the work. It can decide how to do.

3.2. Access Locked files

In older operation systems, sometimes you can open a file for read, and delete the just opened file. Then the opening process crashes, because the file is no more existing.

In newer operation systems (in Windows approximately since Win-XP) the OS-Process locks all used files. Then the delete fails, because the file is locked.

Similar it is on move. Moving a large directory tree on the same device is normally a cheap operation. Only the directory entry is changed, all file contents should not be attached, and also the directory entries on the children files of the moved directory are not attached.

But if the directory is in use, or one of a children or is in use, then move is executed as 'copy' and afterwards try to delete. Whether or not the delete is successful, depends on the locked state of the files.

This chapter needs more experience, because similar questions are also able to found on stackoverflow:

Search string on ecosia.org: "java.nio.file.Files.move copies stackoverflow"

4. Event coupling

Assumed, a file should be copied. Then in a maybe graphic or other fast thread the copying is forced by calling with an callback event. The following test example shows the usage:

Java: copy forcing user thread
//  public void test_copyWithCallback(TestOrg parent) {
//    TestOrg test = new TestOrg("test_copy", 5, parent);
//    FileRemote fsrc = FileRemote.get("q:\\VIDEOS\\telgRingCommAnimation.gif.gif");
//    FileRemote fdst = FileRemote.get("T:/telgRingCommAnimation.gif");
//    fdst.device().activate();                    // start the device thread
//    long time0 = System.nanoTime();
//    FileRemote.CallbackEvent backEvent = new FileRemote.CallbackEvent("test-copycallback", this.callbackCopy, null, this.evSrc);
//    backEvent.occupy(null, true);                // use an event for back info
//    backEvent.setFiles(fsrc, fdst);              // the back event contains the forward event
//    this.callbackDone = false;                   // init definitely state of callback 
//    long time1 = System.nanoTime();
//    fsrc.copyTo(fdst, backEvent);                // this is the copy routine with callback
//    long dTimeCall = System.nanoTime() - time1;
//    waitfinish(backEvent);                       // wait, notify from callback
//    //... this may be normally in the callback operation:
//    String sError = backEvent.errorMsg;          // possible exception message
//    FileRemote.CallbackCmd cmdback = backEvent.getCmd();   // check correctness of operation
//    backEvent.relinquish();                      // relinquish the event for next usage
//    long dTimeRespond = System.nanoTime() - time1;
//    //... end normally in callback operation
//    //========== write test results:             // note: it is not tested whether the file is copied yet.
//    test.expect(cmdback == FileRemote.CallbackCmd.done && sError ==null, 4, "copy operation returns 'done'");
//    test.expect(dTimeCall < 2000000, 3, "time for call < 2 ms = %3.3f", dTimeCall/1000000.0);
//    test.expect(dTimeRespond > 10000000, 2, "time for execution > 10 ms = %3.3f ms", dTimeRespond/1000000.0);
//    System.out.printf("timePrepare = %f, timeCall = %f ms, timeRespond = %f ms\n"
//        , (time1 - time0)/1000000.0, dTimeCall/1000000.0, dTimeRespond/1000000.0);
//    test.finish();
//    try { fdst.device().close(); } catch (IOException e) { }
//  }

Here for the test the result is expected with a wait operation to continue in the same thread. In opposite, for typical graphic applications, the callback operation will be satisfying the approach, it can show results in result of the callback event. This callback operation looks adequate as also in the test:

.Java: copy forcing user thread
  EventConsumer callbackCopy = new EventConsumerAwait(null) {
    @Override public int processEvent ( EventObject ev ) {
      //FileRemote.CallbackEvent backEvent = (FileRemote.CallbackEvent) ev;
      notifyfinish( ev );
      return mEventDonotRelinquish;      // will be relinquished after wait
    }

 
  };

This callback routine should normally also call the backEvent.relinquish(); after all information are gotten from.

The callback operation is here called in the thread which executes the copy, this is the internal device thread for the

The ooutput for this test opeation looks like:

=========================================================================
TestFileRemote
test_copy
  ok: copy operation returns 'done'
  ok: time for call < 2 ms = 0,559
  ok: time for execution > 10 ms = 826,532 ms
timePrepare = 4,333100, timeCall = 0,558800 ms, timeRespond = 826,531700 ms

As you see, the organization of the copy needs ~ 0.5 ms. That is not fast, but fast enough for handling in a graphic thread. If you should wait of copy only one file, in this example the file has only 2 MByte, but it is accessed via WLAN, then you should wait one second and your graphical user interface may block for this time. If the file is longer, or the access is slower, or you want to copy a whole tree of files (a directory or such), then the waiting time is too long for graphic blocking. With the separate thread it is not a problem.

4.1. Copy without callback

is possible, if you do not give a callback instance. Then it is done in the same thread, sensible for a non graphic thread, of course.

4.2. Using only the FileRemote device thread, callback in this thread

This is exactly the version shown in the test example. But for graphical user interfacing it is not sufficient, because the access to graphical widgets can be done (on SWT graphic) only from one thread, the graphic thread.

4.3. Callback executed in a specific thread

Then only the thread should be given for the callback event. This thread should have an event queue, which is true for the GRAL graphic (../Gral/vishiaGui_Gral.html. Then it looks like (snippet from

5. Walker

The idea of using java.nio.file.Files.walkFileTree(pathdir, options, depth1, visitor) comes with this new io package. On java.io.File you can get a list of members of a directory with

Java: old File, get content of directory
  File dir = new File("C:/xyzDirPath");
  File[] files = dir.listFiles();

One problem of this approach is: The file system is volatile. If you have gotten a list of children in a directory, in the next moment the situation on the device can be changed. Another process, in a network, can access the same directory, create also new files.

The next problem is: A directory can also contain a lot of files, and you may only search and handle one or a few specific files. If you get a list, it needs much space.

And the third problem, a directory tree may have a deepness.

5.1. Principle of the walker in java.nio.file.Files

For the reasons about, java.nio.files has introduced a walker facility.

The walker works in the following kind:

  • The java.nio.file.Files.walkFileTree(pathdir, options, depth, visitor) is called with a visitor.

  • It iterates through each directory level, whereby the deepness can be limited by the argument depth. Use 1 to execute only the current level.

  • The operation FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) is called on entry on each directory. Some operations can be processed with the given directory entry. Now this operation can decide whether this entry should be evaluated or not by the return value.

  • The operation FileVisitResult visitFile(T dir, BasicFileAttributes attrs) is called for each file. Also here some operations can be processed with the file, for example copy, get specific content or what else.

  • The operation FileVisitResult visitFileFaild(T dir, IOException exc) is called for each file with problems. The situation is, a file may be contained in a directory list, but the access is faulty.

  • The operation FileVisitResult postVisitDirectory(T dir, IOException exc) is called if the directory is evaluated. In this operation the user can for example restore a filter for the parent level, because the next FileVisitResult preVisitDirectory(…​) or FileVisitResult visitFile(..) is regarded to the parent level. Also a copy of a directory content can be done.

The implementation of the java.nio.file.FileVisitor interface can be done by any proper user implementation.

5.2. Using this walker principle in FileRemote

The java.nio.file.Files.walkFileTree(…​, visitor) is a basically approach. Some more stuff may need to work, and some more stuff is done in the FileRemote class.

To explain how does it work you can follow the example and test routine in org.vishia.fileRemote.test.TestFileRemote.test_copyDirTreeWithCallback(…​). There FileRemote#refreshAndMark(…​) is called. This operation marks firstly some files, which are ready to copy later. This mark operation has the advantage, that the user can check which files are marked before copying, for example sorted by time stamp, look whether all are proper described by the mask, or which are faulty marked, maybe also mark additionally manually some files. This can be done especially by the.File.commander or any other tool.

But also FileRemote#copyDirTreeTo(…​) uses this same approach which is called after mark to copy, also possible to call without mark before.

Lets have a look inside:

Java: Operation as example for FileRemoteAccessor.walkFileTree(…​)
  public void refreshAndMark ( boolean bWait, int depth, int setMark, int setMarkDir, String sMaskSelection, long markSelection
      , FileRemoteWalkerCallback callbackUser, EventWithDst<FileRemoteProgressEvData,?> evBack) {
    if(this.device == null){
      this.device = FileRemote.getAccessorSelector().selectFileRemoteAccessor(getAbsolutePath());
    }
    if(callbackUser !=null)
      Debugutil.stop();
    CmdEvent co = new CmdEvent();
    co.cmd = Cmd.walkSelectMark;
    co.filesrc = this;
    co.depthWalk = depth;
    co.markSet = setMark;
    co.markSetDir = setMarkDir;
    co.selectFilter = sMaskSelection;
    co.selectMask = (int)markSelection;
    co.cycleCallback = 0;                        //calback on any file and dir
    this.device.cmd(bWait, co, evBack);
//    boolean bWait = (evBack ==null);
//    this.device.walkFileTree(this,  bWait, true, setMark, setMarkDir
//          , sMaskSelection, markSelection,  depth,  callbackUser, evBack, false);  //should work in an extra thread.
  }

The walking is delegated to the device, to the operation FileRemoteAccessor#walkFileTree(…​) Generally, how the walker operates should be clarified by the kind of the file system. For the normal PC file system java.nio.files is used, of course. For flexibility the operation call is interfaced with the dynamic linked call.

Most of the arguments are forwarded. The bWait means, the caller should wait. It is true if the progress is not given. Have a look to the called routine for the PC file system:

Java: Operation as example for FileAccessorLocalJava7.walkFileTree(…​)
  @Override public void walkFileTree(FileRemote startDir, final boolean bWait, boolean bRefreshChildren
      , int markSet, int markSetDir
      , String sMask, long bMarkCheck
      , int depth, FileRemoteWalkerCallback callback, EventWithDst<FileRemoteProgressEvData,?> evBack, boolean debugOut)
  { if(bWait){
      // execute it in this thread, therewith wait for success.
//      walkFileTreeExecInThisThread(startDir, bRefreshChildren, markSet, markSetDir
//          , sMask, bMarkCheck, depth, callback, evBack, null, debugOut);
    } else {
      for(WalkerThread wth : this.walkerThread) {
        if(wth.isFree()) {
          if(wth.setOrder(null, evBack)) {
//            wth.ev.setEventData(FileRemoteWalkerEvent.Cmd.refreshAndMark, startDir, bRefreshChildren, depth, markSet, markSetDir, sMask, bMarkCheck, callback, debugOut);
//            wth.evBack = evBack;
//            wth.start();
            break;
          }
        }
      }

      // creates a new Thread with instance of FileWalkerThread for the run routine and the arguments saving:
      
//      FileRemoteAccessor.FileWalkerThread thread = new FileRemoteAccessor.FileWalkerThread(startDir, bRefreshChildren, depth, markSet, markSetDir
//          , sMask, bMarkCheck, callback, debugOut) {
//        @Override public void run() {
//          FileAccessorLocalJava7.this.walkFileTreeExecInThisThread(this.startDir, this.bRefresh, this.co.markSet, this.co.markSetDir
//                , this.sMask, this.bMarkCheck, this.depth, this.callback, ev, debugOut);
//        }
//      };
//      //
//      thread.setPriority(Thread.MIN_PRIORITY +1);
//      thread.start();
    }
  }

As you see here, if bWait==false a new Thread is created and started which does the work. That is a necessary feature if more elaborately work with the file system should be done in a graphic application. The graphic thread should not execute it, because elsewhere the graphic handling blocks for some seconds. This effect is unfortunately known by using some applications, one faulty click and you should wait, cannot abort this operations by another click. It is better that the longer work maybe with wait for access in network is done by another thread.

But this is also complicated because of feedback and control. For that reason the progress event instance is given. This is more explained in the chapter Progress handling and control on walking.

What is done by walking? Look on the called routine:

Java: Operation as example for FileAccessorLocalJava7.walkFileTreeInThisThread(…​)
  protected void walkFileTreeExecInThisThread(
      FileRemote.CmdEvent co
      //FileRemote startDir 
      , boolean bRefreshChildren
//      , int markSet, int markSetDir
//      , String sMask, long bMarkCheck, int depth
      , FileRemoteWalkerCallback callback, EventWithDst<FileRemoteProgressEvData, ?> evBack
      , boolean debugOut)
  {
    int progressFinish = EventConsumer.mEventConsumFinished;
    String sError = null;                        // for unexpected exception message
    try{ 
//      if(evWalker.progress !=null && evWalker.progress.timeOrder !=null) {
//        evWalker.progress.timeOrder.activateCyclic();     // timeOrder back event to inform
//      }
      if(callback !=null) { callback.start(co.filesrc); }
      if(bRefreshChildren) {                     // refreshChildren is for children in FileRemote instance
        co.filesrc.internalAccess().newChildren(); 
      }
      int depth1;
      if(co.depthWalk ==0){ depth1 = Integer.MAX_VALUE; }
      else if(co.depthWalk < 0){ depth1 = -co.depthWalk; }
      else { depth1 = co.depthWalk; }
  
      WalkFileTreeVisitor visitor = new WalkFileTreeVisitor(co.filesrc.itsCluster, bRefreshChildren
          , co, callback, evBack, debugOut);
      Set<FileVisitOption> options = new TreeSet<FileVisitOption>();
      //------------------------------------------- call of the java.nio-walker
      java.nio.file.Files.walkFileTree(co.filesrc.path, options, depth1, visitor);  
      if(visitor.timeOrderProgress !=null ) { visitor.timeOrderProgress.deactivate(); }
    } catch(IOException exc){
      sError = org.vishia.util.ExcUtil.exceptionInfo("FileAccessorLocalJava7.walkFileTree - unexpected Exception; ", exc, 0, 20).toString();
      progressFinish = EventConsumer.mEventConsumerException;
    }
    if(callback !=null) { 
      callback.finished(co.filesrc);               // callback for finish 
    }
    if(evBack !=null ) {                       // back event for finish
      FileRemoteProgressEvData progress = evBack.data();
      progress.done(progressFinish, sError);
      evBack.sendEvent();
    }
  }

Now finally the java.nio walker is called here. But before the FileRemoteProgressEvent progress is activated. It should be cyclically inform its EventConsumer as destination about the progress and at last about finishing. The EventConsumer referred from the progress is prepared before, if necessary. It can be used for example to show a progress bar or the current copying file, interesting if it is a very long file. The progress event can be also used with its back event facility to control the actions what are doint in the walker. For example it is possible to abort copying a very long file by user handling, maybe hold the copy action, abort the whole walking or such. For working with events and the back event see Events.html.

For that reason firstly an more commonly interface FileRemoteWalkerCallback is given, see next chapter.

This interface is used by the operation org.vishia.fileRemote.FileRemote#walkFileTree[FileRemote#walkFileTree(deepness, callback). But this is also a common approach. You can write what ever you want to use here.

5.3. FileRemoteWalkerCallback and derived classes to work

The interface org.vishia.util.SortedTreeWalkerCallback offers a walker interface with the adequate concept, but usable for all tree nodes, independent of the file system and NIO2. The concept is 'steeled' from java.nio.file.FileVisitor, it is a good idea for a universal concept.

The derived interface org.vishia.fileRemote.FileRemoteWalkerCallback. does only contain the specification of the type FileRemote, no more. But from this interface implementations are given:

You can also walk to the FileRemote directory tree, independent respectively uncoupled to the real file system. For example to count number of bytes or files. This is supported in org.vishia.fileRemote.FileRemote#walkFileTree(int depth, FileRemoteWalkerCallback callback).

5.5. The specific walker in

Follow firstly what FileRemote.