10

How to get the short-filename for a long-filename in Windows using Java?

I need to determine the short-filenames of files, stored on a Windows system, using Java(tm).

Ross Ridge
40k7 gold badges94 silver badges124 bronze badges
asked Sep 19, 2013 at 11:23
3

2 Answers 2

10

Self Answer

There are related questions with related answers. I post this solution, however, because it uses Java(tm) code without the need for external libraries. Additional solutions for different versions of Java and/or Microsoft(R) Windows(tm) are welcome.

Main Concept

Main concept lies in calling CMD from Java(tm) by means of the runtime class:

cmd /c for %I in ("[long file name]") do @echo %~fsI

Solution

Tested on Java SE 7 running on Windows 7 system (Code has been reduced for brevity).

 public static String getMSDOSName(String fileName)
 throws IOException, InterruptedException {
 String path = getAbsolutePath(fileName);
 // changed "+ fileName.toUpperCase() +" to "path"
 Process process =
 Runtime.getRuntime().exec(
 "cmd /c for %I in (\"" + path + "\") do @echo %~fsI");
 process.waitFor();
 byte[] data = new byte[65536];
 int size = process.getInputStream().read(data);
 if (size <= 0)
 return null;
 return new String(data, 0, size).replaceAll("\\r\\n", "");
}
public static String getAbsolutePath(String fileName)
 throws IOException {
 File file = new File(fileName);
 String path = file.getAbsolutePath();
 if (file.exists() == false)
 file = new File(path);
 path = file.getCanonicalPath();
 if (file.isDirectory() && (path.endsWith(File.separator) == false))
 path += File.separator;
 return path;
}
answered Sep 19, 2013 at 11:23
Sign up to request clarification or add additional context in comments.

1 Comment

The solution is very good but has a small bug. The fileName.toUpperCase() should remove the toUpperCase since that conversion might do some conversion that is not compatible with how windows charset works. In return windows might not find the file. I had errors with a filename like "20140506_224702_Bäckerstraße.jpg" which through conversion became "20140506_224702_BÄCKERSTRASSE.JPG".
-1

I found a slight problem Osmund's solution. It doesn't work properly for this file name for some reason:

N:\directoryY\tmp\temp\asdfasdf sdf dsfasdf [dfadss]\[asdfas] asdfasd asd asdfasdf ~fdfsdfdfdsfdfdfdfdfd~ TTTm7-9 [RR 1234a5678 A.888 OKOK]a

I'm not really sure why exactly. But if you run the command a slightly different way (using ProcessBuilder), it works. Here is the new code (I am using BufferedReader to read the output, it is much cleaner).

 public static String getMSDOSName(String path) throws IOException, InterruptedException {
 Process process = new ProcessBuilder().command("cmd", "/c", "for %I in (\"" + path + "\") do @echo %~fsI").start();
 process.waitFor();
 try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
 return br.readLine();
 }
 }

This is the output of the original solution vs my solution. The original solution fails to shorten the last path element:

N:\DIRECT~1\tmp\temp\ASDFAS~1\[asdfas] asdfasd asd asdfasdf ~fdfsdfdfdsfdfdfdfdfd~ TTTm7-9 [RR 1234a5678 A.888 OKOK]a
N:\DIRECT~1\tmp\temp\ASDFAS~1\_ASDFA~1.888
answered Jul 11, 2020 at 21:46

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.