code: public static String relativePath(File from, File to) {
          if (from == null || to == null) return null;
          try {
              if (from.isFile()) from = from.getParentFile();
              if (!from.isDirectory()) throw new IllegalArgumentException("Not a directory: " + from);
  
              final String[] fromParts = from.getCanonicalPath().split(Pattern.quote(File.separator));
              List<String> toParts = new ArrayList<>(asList(to.getCanonicalPath().split(Pattern.quote(File.separator))));
  
              int skip = 0; // Skip the common base path
              while (skip < fromParts.length && skip < toParts.size() && fromParts[skip].equals(toParts.get(skip))) {
                  skip++;
              }
              if (skip > 0) toParts = toParts.subList(skip, toParts.size());
  
              // Replace each remaining directory in 'from' by a preceding "../"
              for (int i = fromParts.length; i > skip; i--) toParts.add(0, "..");
  
              // Return the resulting path, joined by seprators.
              return toParts.stream().collect(joining("/"));
          } catch (IOException ioe) {
              throw new IllegalStateException("I/O exception calculating relative path from \""
                      + from + "\" to \"" + to + "\": " + ioe.getMessage(), ioe);
          }
      }
docs: Returns the relative path from one file to another.
  
  @param from The source file.
  @param to   The target file.
  @return The relative path from the source to the target file.