In some rare occasions you might want to find out the short filename of a file in Windows (for example to run legacy code). After looking around on the net, I couldn't find a java function to do it. And no, messing around with the output of dir /x
is not a pretty solution.
Microsoft provides a Windows API function called GetShortPathName, which you can call from java using JNI. Too lazy actually messing around with JNI I found a package called NativeCall which allows calling a Windows API function from java without using JNI.
Here's the code for retrieving the short (8.3) filename given a long filename. Have fun with it. Don't forget to download the nativecall package and to add it to your classpath. For the lazy people I've made a zip containing this class, the two jars and how to execute it.
import com.eaio.nativecall.*; public class EightPointThree { public static void main(String[] args) { String usage = "java " + EightPointThree.class.getName() + " longfilename"; if (args.length != 1) { System.err.println(usage); System.exit(1); } else { System.out.println(getEightPointThree(args[0])); } } /** * returns the short filename (8.3) for a file in Windows * * @param longFileName * @return a string with the short filename, or null if an error occurred or the * file does not exist. */ public static String getEightPointThree(String longFileName) { try { // the result String shortName = null; NativeCall.init(); IntCall ic = new IntCall("GetShortPathNameW"); try { // size of result is at most the long file name (times 2 for the // number // of bytes) Struct resultStruct = new Struct(longFileName.length() * 2); int iResultCode = ic.executeCall(new Object[] { longFileName, resultStruct, new Integer(longFileName.length()) }); if (iResultCode > 0) { // iResultCode is length byte[] data = resultStruct.getData(); int length = data.length > (iResultCode * 2) ? (iResultCode * 2) : data.length; byte[] data2 = new byte[length]; System.arraycopy(data, 0, data2, 0, length); // structResult contains letter space letter space letter String structResult = new String(data2); // remove spaces in between StringBuffer result = new StringBuffer(); for (int i = 0; i < structResult.length(); i += 2) result.append(structResult.charAt(i)); shortName = result.toString().trim(); if (shortName.equals("")) shortName = longFileName; } } finally { ic.destroy(); } return shortName; } catch (Exception e) { System.err.println("Exception of type " + e.getClass().getName() + ":\n" + e.getMessage()); e.printStackTrace(); } return null; } }
Note that your file system must be configured to be backwards compatible with good old DOS. Windows (by default) generates a
8.3 filename for a newly created files. By setting the registry key HKEY_LOCAL_MACHINE/SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation
however (0 to enable 8.3 name creation, or to 1 to disable), no 8.3 filenames are created anymore!
Related (just to help you find this page):