Как получить короткие имена файлов в Windows, используя Java?

Как получить короткое имя для длинного имени в Windows, используя Java?

Мне нужно определить короткие имена файлов, хранящихся в системе Windows, используя Java(tm).

1 ответ

Решение

Самостоятельный ответ

Есть связанные вопросы с соответствующими ответами. Однако я публикую это решение, потому что оно использует код Java(tm) без необходимости использования внешних библиотек. Дополнительные решения для различных версий Java и / или Microsoft(R) Windows(TM) приветствуются.

Основная концепция

Основная концепция заключается в вызове CMD из Java(tm) с помощью класса времени выполнения:

cmd / c для%I in ("[длинное имя файла]") do @echo %~fsI

Решение

Протестировано на Java SE 7, работающем в системе Windows 7 (код был сокращен для краткости).

    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;
}

Я нашел решение небольшой проблемы Осмунда. По какой-то причине он не работает должным образом для этого имени файла:

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

Я не совсем уверен, почему именно. Но если вы запустите команду немного другим способом (используя ProcessBuilder), она сработает. Вот новый код (я использую BufferedReader для чтения вывода, он намного чище).

    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();
        }
    }

Это результат исходного решения по сравнению с моим решением. Исходное решение не может сократить последний элемент пути:

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
Другие вопросы по тегам