create shortcuts in java with lib JShortcut - java

I want to create shortcuts inwindows with code, I use the library here:
http://alumnus.caltech.edu/~jimmc/jshortcut/jshortcut/README.html
also the corresponding codes:
import net.jimmc.jshortcut.JShellLink;
public class remove {
public static void main(String[] args) throws Exception{
String path = new String ("/home/test.csv");
readAndDelete(path, true, StandardCharsets.UTF_8);
}
private static void readAndDelete(String path, boolean ignoreHeader,Charset encoding) throws IOException {
File file = new File(path);
CSVParser parser = CSVParser.parse(file, encoding,CSVFormat.DEFAULT.withHeader());
List<CSVRecord> records = parser.getRecords();
List<String> docRecord = new ArrayList<String>();
List<String> shortpath = new ArrayList<String>();
for (CSVRecord doctype : records){
docRecord.add(doctype.get(0).toString());
shortpath.add(doctype.get(1).toString());
}
int recordlength = docRecord.size();
for(String eachdocRecord:docRecord){
try {
Path pathtemp=Paths.get(eachdocRecord);
Files.delete(pathtemp);
} catch (NoSuchFileException x) {
System.err.format("%s: no such" + " file or directory%n", path);
} catch (DirectoryNotEmptyException x) {
System.err.format("%s not empty%n", path);
} catch (IOException x) {
// File permission problems are caught here.
System.err.println(x);
}
}
for(int i=0; i<recordlength; i++){
JShellLink link = new JShellLink();
String pointpath=shortpath.get(i);
String originalpath = docRecord.get(i);
String[] parts = pointpath.split("\\\\");
int partssize= parts.length;
String name=parts[partssize-1];
String[] originalparts = originalpath.split("\\\\");
int originalsize = originalparts.length;
int lastlength = originalparts[originalsize-1].length();
String foldername = originalpath.substring(0,originalpath.length()-lastlength);
link.setFolder(foldername);
link.setName(name);
link.setPath(pointpath);
link.save();
}
}
}
I run it in windows command prompt, but always exception:
Exception in thread "main" java.lang.NoClassDefFoundError:net/jimmc/jshortcut/JShellLink
I compiled the .class successfully ...
Anyone could save nme ... thanks a lot

Regardless of anything else that might be wrong (I did not read the entire code) the exception is quite clear - JShellLink is not on your classpath. How to do it best depends on your use case - README suggests editing Manifest file when you build to .jar, it should also be possible to use Maven to take care of that, and any IDE should have been able to take care of classpaths for you. As far as I can tell however your use case looks something like
javac remove.java
java remove
(By the way, class names and class file names should start with upper case, that's the standard)
In that case the simplest way to do that would be to use:
java -cp .;jshortcut.jar remove
We add current directory (due to JShortcut wanting to have it's dll on classpath, just to be sure) as well as the jar containing classes you use to the classpath. If you're on Unix system use : instead of ;.

Related

Files.copy not recognising binary files on Windows (Java)

So I am trying to copy some files with Files.copy(), and while it is working fine in Mac, and works to copy text files on Windows, when I try to copy a binary file I just get the error:
java.nio.file.NoSuchFileException: C:\path\to\file
My function is:
private void copyFiles()
{
ArrayList<String> temp = new ArrayList<>(); //This is set up outside the function
temp.add("file1");
temp.add("file2"); //etc
String AlphaSimFileName = "folderName"; //This is actually set outside the function
String currentDir = System.getProperty("user.dir");
Path baseAlphaName = Paths.get(currentDir, AlphaSimFileName);
Path baseDirectoryName = Paths.get(currentDir, name);
System.out.println(""+baseAlphaName.toString());
System.out.println(""+baseDirectoryName.toString());
// for (String l: MyFunctions.getFilesAsString()) //gives the list of files to copy.
for (String l: temp)
{
Path p1 = Paths.get(baseAlphaName.toString(), l);
Path p2 = Paths.get(baseDirectoryName.toString(), l);
try
{
Files.copy(p1, p2, StandardCopyOption.REPLACE_EXISTING);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Anyone have any idea why this is happening?
(Posted on behalf of the OP).
The reason for this was that Windows was automatically hiding file extensions, so the file that I was trying to move (i.e. without the extension) didn't exist.
Try doing it manually first. Use \\ instead of \ when you hardcode the path for Windows using Java. Also, the file extension may be missing.

how to change the file path based on the OS

i have a class which reads the list available in particular location,
the following is my code,
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ExceptionInFileHandling {
#SuppressWarnings({ "rawtypes", "unchecked" })
public static void GetDirectory(String a_Path, List a_files, List a_folders) throws IOException {
try {
File l_Directory = new File(a_Path);
File[] l_files = l_Directory.listFiles();
for (int c = 0; c < l_files.length; c++) {
if (l_files[c].isDirectory()) {
a_folders.add(l_files[c].getName());
} else {
a_files.add(l_files[c].getName());
}
}
} catch (Exception ex){
ex.printStackTrace();
}
}
#SuppressWarnings("rawtypes")
public static void main(String args[]) throws IOException {
String filesLocation = "asdfasdf/sdfsdf/";
List l_Files = new ArrayList(), l_Folders = new ArrayList();
GetDirectory(filesLocation, l_Files, l_Folders);
System.out.println("Files");
System.out.println("---------------------------");
for (Object file : l_Files) {
System.out.println(file);
}
System.out.println("Done");
}
}
in this the file path can be passed as argument and that should be taken up based on the OS,
filePath.replaceAll("\\\\|/", "\\" + System.getProperty("file.separator"))
is this correct?
There are better ways to use file paths...
// Don't do this
filePath.replaceAll("\\\\|/", "\\" + System.getProperty("file.separator"))
Use java.nio.file.path:
import java.nio.file.*;
Path path = Paths.get(somePathString);
// Here is your system independent path
path.toAbsolutePath();
// Or this works too
Paths.get(somePathString).toAbsolutePath();
Use File.seperator:
// You can also input a String that has a proper file seperator like so
String filePath = "SomeDirectory" + File.separator;
// Then call your directory method
try{
ExceptionInFileHandling.GetDirectory(filePath, ..., ...);
} catch (Exception e){}
So a simple change to your method will now work cross platform:
#SuppressWarnings({ "rawtypes", "unchecked" })
public static void GetDirectory(String a_Path, List a_files, List a_folders) throws IOException {
try {
// File object is instead constructed
// with a URI by using Path.toUri()
// Change is done here
File l_Directory = new File(Paths.get(a_Path).toUri());
File[] l_files = l_Directory.listFiles();
for (int c = 0; c < l_files.length; c++) {
if (l_files[c].isDirectory()) {
a_folders.add(l_files[c].getName());
} else {
a_files.add(l_files[c].getName());
}
}
} catch (Exception ex){
ex.printStackTrace();
}
}
You can use forward slashes as directory separators on Windows as well when calling File constructor.
why you are not adding java defined file separator instead of creating a string then replacing all.
try it like
String filesLocation = "asdfasdf"+File.separator+"sdfsdf"+File.separator;
The answer from you should be correct. There is another similiar thread with answer :
Java regex to replace file path based on OS
Platform independent paths in Java
You could generate a Path object from the passed argument. Then you would not need to handle the file separator on your own.
public static void main(String[] args) {
Path path = Paths.get(args[0]);
System.out.println("path = " + path.toAbsolutePath());
}
The code is able to handle following passed arguments.
foo\bar
foo/bar
foo\bar/baz
foo\\bar
foo//baz
foo\\bar//baz
...
First, you should not used relative path like asdfasdf/sdfsdf/. It's a big source of bugs as your path depends on your working directory.
That thing said, your replaceAll is quite good but it can be improved like this :
filePath.replaceAll(
"[/\\\\]+",
Matcher.quoteReplacement(System.getProperty("file.separator")));
Using quoteReplacement is adviced in replaceAll documentation
Returns a literal replacement String for the specified String. This method produces a String that will work as a literal replacement s in the appendReplacement method of the Matcher class. The String produced will match the sequence of characters in s treated as a literal sequence. Slashes ('\') and dollar signs ('$') will be given no special meaning.
You need to use java.io.File.separatorChar to The system-dependent default name-separator character.
String location = "usr"+java.io.File.separatorChar+"local"+java.io.File.separatorChar;
org.apache.commons.io.FilenameUtils contains a lot of useful methods, for instance separatorsToSystem(String path) converts separators in given path in accordance with OS which you are using.
Use the below method to know about OS file separator and then replaceAll previous separator with this methods.
System.getProperty("file.separator");
Why you just dont use "/". It is acceptable for both linux and windows as path seperator.

read file system structure from java

Is it possible to read all the names of folders (not sub-folders) inside a directory and save the list in an ArrayList, etc ?
e.g- if a directory has the following folders inside it- CLIENT1, CLIENT2, CLIENT3, etc.
I want the ArrayList to be something like this- [CLIENT1, CLIENT2, CLIENT3, etc].
The folders are in an unix server, so either java code or a shell script(bash/tcsh/etc) or their combination would do.
Try this:
File dir = new File("directoryName");
File temp;
String[] children = dir.list();
if (children !=null) {
for (int i=0; i<children.length; i++) {
temp = new File(children[i]);
if(temp.isDirectory()) //add children[i] to arrayList
}
}
The below Java code snippet should help you. It will return the list of all folders within a directory.It may return an empty list based on the manner in which you deal with any possible IO exception.
public List<String> getDirectoriesInFolder(String folderPath)
{
List<String> folderNames = new ArrayList<String>();
try
{
File directory = new File (folderPath);
String[] allFilesInFolder = directory.list();
for(String fileName : allFilesInFolder)
{
File f = new File(fileName);
if(f.isDirectory)
{
folderNames.add(fileName);
}
}
}
catch(IOException iex)
{
//Do any exception handling here...
}
return folderNames;
}
If you want to do it using Shell scripting then the guidance provided on the below links should help you come to a solution:
help with script to list directories
bash: put output from ls into an array
This would feel slightly cleaner to me than a blunt iteration constructing new File() each time.
public class DirFilter implements FileFilter {
public static FileFilter INSTANCE = new DirFilter();
#Override
public boolean accept(File file) {
return file.isDirectory();
}
}
File startDir = .....;
List<File> children = Arrays.asList(startDir.listFiles(DirFilter.INSTANCE));

Delete Files with same Prefix String using Java

I have around 500 text files inside a directory with each with the same prefix in their filename, for example: dailyReport_.
The latter part of the file is the date of the file. (For example dailyReport_08262011.txt, dailyReport_08232011.txt)
I want to delete these files using a Java procedure. (I could go for a shell script and add it a job in the crontab but the application is meant to used by laymen).
I can delete a single file using something like this:
try{
File f=new File("dailyReport_08232011.txt");
f.delete();
}
catch(Exception e){
System.out.println(e);
}
but can I delete the files having a certain prefix? (e.g. dailyReport08 for the 8th month) I could easily do that in shell script by using rm -rf dailyReport08*.txt .
But File f=new File("dailyReport_08*.txt"); doesnt work in Java (as expected).
Now is anything similar possible in Java without running a loop that searches the directory for files?
Can I achieve this using some special characters similar to * used in shell script?
No, you can't. Java is rather low-level language -- comparing with shell-script -- so things like this must be done more explicetly. You should search for files with required mask with folder.listFiles(FilenameFilter), and iterate through returned array deleting each entry. Like this:
final File folder = ...
final File[] files = folder.listFiles( new FilenameFilter() {
#Override
public boolean accept( final File dir,
final String name ) {
return name.matches( "dailyReport_08.*\\.txt" );
}
} );
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
You can use a loop
for (File f : directory.listFiles()) {
if (f.getName().startsWith("dailyReport_")) {
f.delete();
}
}
Java 8 :
final File downloadDirectory = new File("directoryPath");
final File[] files = downloadDirectory.listFiles( (dir,name) -> name.matches("dailyReport_.*?" ));
Arrays.asList(files).stream().forEach(File::delete)
With Java 8:
public static boolean deleteFilesForPathByPrefix(final String path, final String prefix) {
boolean success = true;
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get(path), prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) {
success = false;
e.printStackTrace();
}
return success;
}
Simple version:
public static void deleteFilesForPathByPrefix(final Path path, final String prefix) {
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path, prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) { // empty
}
}
Modify the Path/String argument as needed. You can even convert between File and Path. Path is preferred for Java >= 8.
I know I'm late to the party. However, for future reference, I wanted to contribute a java 8 stream solution that doesn't involve a loop.
It may not be pretty. I welcome suggestions to make it look better. However, it does the job:
Files.list(deleteDirectory).filter(p -> p.toString().contains("dailyReport_08")).forEach((p) -> {
try {
Files.deleteIfExists(p);
} catch (Exception e) {
e.printStackTrace();
}
});
Alternatively, you can use Files.walk which will traverse the directory depth-first. That is, if the files are buried in different directories.
Use FileFilter like so:
File dir = new File(<path to dir>);
File[] toBeDeleted = dir.listFiles(new FileFilter() {
boolean accept(File pathname) {
return (pathname.getName().startsWith("dailyReport_08") && pathname.getName().endsWith(".txt"));
}
for (File f : toBeDeleted) {
f.delete();
}
There isn't a wildcard but you can implement a FilenameFilter and check the path with a startsWith("dailyReport_"). Then calling File.listFiles(filter) gives you an array of Files that you can loop through and call delete() on.
I agree with BegemoT.
However, just one optimization:
If you need a simple FilenameFilter, there is a class in the Google packages.
So, in this case you do not even have to create your own anonymous class.
import com.google.common.io.PatternFilenameFilter;
final File folder = ...
final File[] files = folder.listFiles(new PatternFilenameFilter("dailyReport_08.*\\.txt"));
// loop through the files
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
Enjoy !
You can't do it without a loop. But you can enhance this loop. First of all, ask you a question: "what's the problem with searching and removing in the loop?" If it's too slow for some reason, you can just run your loop in a separate thread, so that it will not affect your user interface.
Other advice - put your daily reports in a separate folder and then you will be able to remove this folder with all content.
or in scala
new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
Have a look at Apache FileUtils which offers many handy file manipulations.

how to set Hidden proprerty of a file

I'm trying to create a static method that let me hide a file.
I've found some possible way to do that and I wrote this:
public static void hide(File src) throws InterruptedException, IOException {
if(System.getProperty("os.name").contains("Windows"))
{
Process p = Runtime.getRuntime().exec("attrib +h " + src.getPath());
p.waitFor();
}
else
{
src.renameTo(new File(src.getParent()+File.separator+"."+src.getName()));
}
}
Unfortunatley this isn't working in windows and neither on Ubuntu...
In Oracle's tuorials I've found this way
Path file = ...;
Files.setAttribute(file, "dos:hidden", true);
but I don't know how to use it because my JDK doesn't have the class "Path".
Can anyone help me with a method that can work in unix OS and Windows?
The Path class was introduced in Java 7.
Before Java 7 there was no built-in way to access properties like this, so you'll have to do something similar to what you're trying (and on Unix-y OS there is no "hidden property", but all files that start with a . are hidden by default).
Regarding your exec() call there's a great (if a bit old) article that lists all the stuff that can go wrong and how to fix it (it's quite an involved process, unfortunately).
And a minor note: new File(src.getParent()+File.separator+"."+src.getName()) can be replaced by new File(src.getParent(), "." + src.getName()), which would be a bit cleaner.
If a file as not parent, getParent() will return null. Perhaps what you wanted for unix was
src.renameTo(new File(src.getParent(), '.'+src.getName()));
Path is available in Java 7.
you won't be able to achieve this with standard JDK code. The File class offers an isHidden method, however, it states clearly that the concept of hidden is file system dependent:
Tests whether the file named by this
abstract pathname is a hidden file.
The exact definition of hidden is
system-dependent. On UNIX systems, a
file is considered to be hidden if its
name begins with a period character
('.'). On Microsoft Windows systems, a
file is considered to be hidden if it
has been marked as such in the
filesystem.
As such you need to write platform specific code (JNI?) to hide a file.
Operating system detection code:
public class OperatingSystemUtilities
{
private static String operatingSystem = null;
private static String getOperatingSystemName()
{
if (operatingSystem == null)
{
operatingSystem = System.getProperty("os.name");
}
return operatingSystem;
}
public static boolean isWindows()
{
String operatingSystemName = getOperatingSystemName();
return operatingSystemName.startsWith("Windows");
}
public static boolean isMacOSX()
{
String operatingSystemName = getOperatingSystemName();
return operatingSystemName.startsWith("Mac OS X");
}
public static boolean isUnix()
{
return !isWindows();
}
}
Hiding the file code:
public static String hideFile(String filePath) throws IOException
{
Path path = Paths.get(filePath);
if (OperatingSystemUtilities.isWindows())
{
Files.setAttribute(path, "dos:hidden", Boolean.TRUE, LinkOption.NOFOLLOW_LINKS);
return path.toString();
} else if (OperatingSystemUtilities.isUnix())
{
String filename = path.getFileName().toString();
if (filename.startsWith("."))
{
return path.toString();
}
// Keep trying to rename
while (true)
{
Path parent = path.toAbsolutePath().getParent();
Path newPath = Paths.get(parent + File.separator + "." + filename);
// Modify the file name when it exists
if (Files.exists(newPath))
{
int lastDotIndex = filename.lastIndexOf(".");
if (lastDotIndex == -1)
{
lastDotIndex = filename.length();
}
Random random = new Random();
int randomNumber = random.nextInt();
randomNumber = Math.abs(randomNumber);
filename = filename.substring(0, lastDotIndex) + randomNumber + filename.substring(lastDotIndex, filename.length());
continue;
}
Files.move(path, newPath);
return newPath.toString();
}
}
throw new IllegalStateException("Unsupported OS!");
}
Note that you have to pay attention to avoid a file name clash when renaming to hide the file on Unix. This is what the code implements despite it being unlikely.

Categories