Приложение Java не может записывать/читать файл сериализации при установке в C:/Program Files — java.io.FileNotFoundException: (Доступ запрещен)

Мое приложение использует этот код для постоянного сохранения ArrayList, чтобы его можно было вызвать при перезапуске приложения.

    private static void storeDevices() {
    // Object serialization
    try {
        FileOutputStream fos = new FileOutputStream("devices.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(devices);
        oos.flush();
        oos.close();
    }
    catch(Exception e) {
        showAlert("Store Devices", "Exception storing devices to file: " + e);
    } 
}

Все работает нормально, когда я запускаю Netbeans. Я завернул приложение в установщик (используя Launch4J и Inno Setup Compiler), и когда я устанавливаю приложение в C:/Program Files/MyApp (в Windows 7), приведенный выше код дает следующее исключение:

Исключение хранения устройств в файле: java.io.FileNotFoundException: devices.ser (доступ запрещен)

Однако, когда я устанавливаю в C:/MyApp, все работает нормально.

Это как-то связано с разрешением на чтение/запись, унаследованным от каталога C:/Program Files? Я знаю, что могу решить эту проблему, создав файл в каталоге C:/temp или где-то в этом роде, но я не хочу прибегать к этому. Итак, есть ли способ писать/читать файлы в моем каталоге C:/Program Files/MyApp?


person ban-geoengineering    schedule 28.03.2013    source источник
comment
попробуй установить с запуском от имени администратора   -  person Abubakkar    schedule 28.03.2013
comment
Я думаю, что эта проблема обсуждалась в более старом вопросе: stackoverflow.com/questions/7865160/   -  person redc0w    schedule 28.03.2013
comment
Я действительно не хочу работать от имени администратора - я хочу, чтобы это было как можно более нормальным/правильным. Другая ссылка SO тоже не помогла. Но все равно спасибо вам обоим.   -  person ban-geoengineering    schedule 28.03.2013
comment
Может быть, я обхожу это неправильным путем. Я только что обнаружил Preferences API — ibm.com/developerworks/library /j-prefapi/index.html - звучит многообещающе, но не рекомендует использовать с ним сериализуемые объекты, поэтому я надеюсь, что есть лучшее решение??   -  person ban-geoengineering    schedule 28.03.2013
comment
Возможно, использование переменных среды было бы хорошим способом получить правильный каталог для хранения данных приложения, например. System.getenv(ALLUSERSPROFILE) или System.getenv(APPDATA) - но являются ли они кросс-платформенными??   -  person ban-geoengineering    schedule 28.03.2013


Ответы (2)


начиная с Windows Vista, ни одно приложение не может получить доступ к области системных папок без явной аутентификации. (папки типа program-file/window32/ и т.д....) Для установленного приложения аутентификация выполняется установщиком Windows.

Чтобы иметь доступ (чтение/запись), либо вам нужно работать от имени администратора, либо вам нужно изменить права доступа к этой папке (что не рекомендуется)

person Ankit    schedule 28.03.2013

Мое решение состояло в том, чтобы использовать переменные среды, чтобы получить правильный каталог для хранения данных приложения. Вот метод, который я создал:

private String getAppDataDirectory(String subDirectory, boolean create) {

    String appDataDirectory;
    try {
        appDataDirectory = System.getenv("APPDATA"); //Windows
        //todo - could try "ALLUSERSPROFILE"
        if (appDataDirectory != null) {
            appDataDirectory += File.separator + subDirectory + File.separator;
        }
        else { //appDataDirectory is null
            appDataDirectory = System.getenv("HOME"); //Unix
            if (appDataDirectory != null) {
                appDataDirectory +=  File.separator + subDirectory + File.separator;
            }
            else { //appDataDirectory is still null
                throw new Exception("Could not access APPDATA or HOME environment variables");
            }
        }
    }
    catch(Exception e) {
        e.printStackTrace();
        appDataDirectory = "";
    }

    if (create && appDataDirectory != null && appDataDirectory.length() > 0) {
        try {
            File dir = new File(appDataDirectory);
            dir.mkdir();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    //log("appDataDirectory: " + appDataDirectory);
    return appDataDirectory;
}
person ban-geoengineering    schedule 08.04.2013