Каков наилучший способ найти домашний каталог пользователей в Java?
трудность заключается в том, что он должен быть кросс-платформенным. Windows 2000, XP, Vista, OSX, Linux, другие варианты unix. Я ищу фрагмент кода, который может сделать это для всех платформ, и способ обнаружения платформы.
теперь вы должны знать о ошибка 4787931 это user.home не работает правильно, поэтому, пожалуйста, не предоставляйте мне ответы на учебники, я могу найти их сам в руководствах.
8 ответов:
ошибка, на которую вы ссылаетесь (ошибка 4787391), была исправлена в Java 8. Даже если вы используете более старую версию Java,
System.getProperty("user.home")подход, вероятно, все еще лучший. Элементuser.homeподход, кажется, работает в очень большом числе случаев. 100% пуленепробиваемое решение для Windows сложно, потому что Windows имеет смещенную концепцию того, что означает домашний каталог.
Еслиuser.homeне достаточно хорошо для вас я бы предложил выбрать определениеhome directoryдля windows и с его помощью, получая соответствующая переменная окружения сSystem.getenv(String).
На самом деле с Java 8 правильный способ заключается в использовании:
System.getProperty("user.home");ошибка JDK-6519127 была исправлена и" несовместимости между JDK 8 и JDK 7 " раздел заметки гласит:
область: основные библиотеки / java.Лэнг
справка
шаги, используемые для определения домашнего каталога пользователя в Windows, изменились, чтобы следовать рекомендуемому Microsoft подходу. Это изменение могли бы быть наблюдаемый на более старых выпусках Windows или где реестр параметры или переменные среды устанавливаются в другие каталоги. Природа несовместимости
behavioral RFE 6519127несмотря на то, что вопрос старый, я оставляю это для дальнейшего использования.
концепция домашнего каталога кажется немного расплывчатой, когда речь заходит о Windows. Если переменные среды (HOMEDRIVE / HOMEPATH / USERPROFILE) недостаточно, возможно, вам придется прибегнуть к использованию собственных функций через JNI или JNA. SHGetFolderPath позволяет извлекать специальные папки, такие как Мои Документы (CSIDL_PERSONAL) или Локальные Настройки\Данные Приложения (CSIDL_LOCAL_APPDATA).
пример кода JNA:
public class PrintAppDataDir { public static void main(String[] args) { if (com.sun.jna.Platform.isWindows()) { HWND hwndOwner = null; int nFolder = Shell32.CSIDL_LOCAL_APPDATA; HANDLE hToken = null; int dwFlags = Shell32.SHGFP_TYPE_CURRENT; char[] pszPath = new char[Shell32.MAX_PATH]; int hResult = Shell32.INSTANCE.SHGetFolderPath(hwndOwner, nFolder, hToken, dwFlags, pszPath); if (Shell32.S_OK == hResult) { String path = new String(pszPath); int len = path.indexOf(''); path = path.substring(0, len); System.out.println(path); } else { System.err.println("Error: " + hResult); } } } private static Map<String, Object> OPTIONS = new HashMap<String, Object>(); static { OPTIONS.put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); OPTIONS.put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); } static class HANDLE extends PointerType implements NativeMapped { } static class HWND extends HANDLE { } static interface Shell32 extends Library { public static final int MAX_PATH = 260; public static final int CSIDL_LOCAL_APPDATA = 0x001c; public static final int SHGFP_TYPE_CURRENT = 0; public static final int SHGFP_TYPE_DEFAULT = 1; public static final int S_OK = 0; static Shell32 INSTANCE = (Shell32) Native.loadLibrary("shell32", Shell32.class, OPTIONS); /** * see http://msdn.microsoft.com/en-us/library/bb762181(VS.85).aspx * * HRESULT SHGetFolderPath( HWND hwndOwner, int nFolder, HANDLE hToken, * DWORD dwFlags, LPTSTR pszPath); */ public int SHGetFolderPath(HWND hwndOwner, int nFolder, HANDLE hToken, int dwFlags, char[] pszPath); } }
System.getProperty("user.home");посмотреть документация.
другие ответили на вопрос передо мной, но полезная программа для печати всех доступных свойств:
for (Map.Entry<?,?> e : System.getProperties().entrySet()) { System.out.println(String.format("%s = %s", e.getKey(), e.getValue())); }
поскольку я искал версию Scala, все, что я мог найти, это код JNA McDowell выше. Я включаю здесь свой порт Scala, так как в настоящее время нет более подходящего места.
import com.sun.jna.platform.win32._ object jna { def getHome: java.io.File = { if (!com.sun.jna.Platform.isWindows()) { new java.io.File(System.getProperty("user.home")) } else { val pszPath: Array[Char] = new Array[Char](WinDef.MAX_PATH) new java.io.File(Shell32.INSTANCE.SHGetSpecialFolderPath(null, pszPath, ShlObj.CSIDL_MYDOCUMENTS, false) match { case true => new String(pszPath.takeWhile(c => c != '')) case _ => System.getProperty("user.home") }) } } }Как и в версии Java, вам нужно будет добавить Java Native Access, включая оба файла jar, в ваши библиотеки ссылок.
приятно видеть, что JNA теперь делает это намного проще, чем когда исходный код был опубликован.
Я бы использовал алгоритм, подробно описанный в отчете об ошибке, используя систему.getenv (строка) и резервный вариант использования пользователя.свойство dir, если ни одна из переменных среды не указывает допустимый существующий каталог. Это должно работать кросс-платформенно.
Я думаю, что под Windows, что вы действительно после это условная "документы пользователя".
Если вы хотите что-то, что хорошо работает на Windows есть пакет под названием WinFoldersJava который обертывает собственный вызов, чтобы получить "специальные" каталоги в Windows. Мы используем его часто и он хорошо работает.
Comments