2012-11-04 2 views
2

Я пишу приложение (для образовательных целей), которому необходимо использовать систему управления базами данных (я написал свою очень примитивную СУБД, это часть задачи). И я хочу убедиться, что в любое время, когда выполняется мое приложение, содержимое всех таблиц верное. Для этого я написал метод, который просматривает каждый файл и делает необходимые проверки. Проблема в том, что я хочу вызывать этот метод только один раз, когда приложение запускает и запрещает доступ к файлам, чтобы гарантировать, что никто не изменил их содержимое во время работы моей программы.Запретить доступ к файлу для всех других процессов?

Я использую следующий подход. Когда приложение запускается, я инициализирую InputStreamReader и OutputStreamWriter, сохраните их и закройте их, только когда мое приложение будет завершено.

Часть метода инициализации:

FileInputStream fis = new FileInputStream(file); 
FileOutputStream fos = new FileOutputStream(file, true); 
InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); 
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); 

this.tables.get(table).put("fis", fis); 
this.tables.get(table).put("fos", fos); 
this.tables.get(table).put("isr", isr); 
this.tables.get(table).put("osw", osw); 

Закрыть метод:

try { 
    for(Map<String, Object> table_map: tables.values()) { 
     OutputStreamWriter osw = (OutputStreamWriter)table_map.get("osw"); 
     InputStreamReader isr = (InputStreamReader)table_map.get("isr"); 

     if (osw != null) 
      osw.close(); 
     if (isr != null) 
      isr.close(); 
    } 
} 
catch (IOException e) { 
    throw new DBException("Closing error"); 
} 

Частично этот подход работает, потому что, когда я пытаюсь изменить любой из этих файлов с помощью MS Notepad, Я получаю следующую ошибку:

«Процесс не может получить доступ к файлу, так как он используется другим процессом »

Вот что я хочу видеть. Но если я использую Notepad ++, я могу вносить какие-либо изменения, когда мое приложение работает, это не то, что я ожидаю увидеть. Итак, что я могу сделать, чтобы ни один другой процесс не мог изменять мои файлы?

Я пытался использовать FileLock, но он запрещает доступ только для моего процесса, если я не ошибаюсь.

Извините за моего бедного английского, надеюсь, вы поймете мой вопрос в любом случае.

+2

Вместо использования карты я бы использовал объект, который содержит 'osw' и' isr'. Я бы закрепил их для повышения производительности, и я бы не сохранил исходные потоки, поскольку они вам не нужны. Я бы использовал правильную IDE, которая поможет вам писать, запускать и отлаживать код. –

+2

Самый простой способ запретить доступ к файлу - переименовать его. Таким образом, вы не сможете получить доступ к нему, если не знаете, что вызвал файл, вы можете изменить его расширение. –

+1

Yup, переименовывая файл, обычно работает с удовольствием ... просто переименуйте его в нечто «очень уникальное», например filename.UUID.ext. См. Doco: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html – corlettk

ответ

2

Я не уверен, что это проблема, которую стоит решить. Какой бы подход вы ни выбрали, кто-то с правильными привилегиями может, вероятно, отменить вашу защиту файлов и в любом случае внести изменения.

Лучше всего сосредоточиться на изящной обработке недопустимых данных и в противном случае доверять тому, что находится в файле. Добавление проверки целостности (для каждой строки или таблицы) затруднит кому-то случайное или злонамеренное изменение ваших данных таким образом, чтобы он выглядел «действительным».

+0

Ну, сначала я хочу ответить вам, что проверка целостности довольно ресурсоемкая. Например, я проверяю, идут ли строки с более высокими значениями первичного ключа после строк с более низкими. Чтобы выполнить эту проверку, метод должен прочитать весь файл и проанализировать каждую строку, чтобы получить значение первичного ключа. Но потом я подумал немного и решил, что этот чек достаточно бесполезен. Если пользователи пытаются умышленно испортить правильную работу программы, они должны быть готовы к неожиданным результатам. Мне нужно только для предотвращения сбоя программы, поэтому, я полагаю, проверок строк в основных методах (таких как вставка) будет достаточно. –

+0

Небольшое замечание - я не решил, что этот ресурсоемкий чек совершенно бесполезен. Это полезно, когда приложение запускается, но нет смысла вызывать его каждый раз, когда я хочу выбирать, обновлять, вставлять или удалять данные. Следовательно, нет необходимости в блокировании файлов. –

2

Если вы читали раздел «зависимостей Platform» в java.nio.channels.FileLock docsyou видеть, что:

  • FileLocks не (только) для блокировки внутри один JVM, но и для всех процессов на компьютере.
  • Файловые замки (обратите внимание на различное правописание) - это большая платформа и конфигурация.

Итак, вы, основной вопрос, должны спросить себя: Какая защита действительно нужно?

Если вы хотите, чтобы защититься от запуска ваших программки несколько раз на те же данные, можно предположить, что ваша программа «ведет себя хорошо» и

  • использование FileLocks или
  • использовать файл блокировки маркеров или
  • использовать «грязный/заблокированный» маркер внутри файла

Если вы хотите защитить от , любая другая программа, то вы потеряны, как вы видели в сценарии Notepad ++: учитывая все платформы и все возможные способы обойти блокировки и используя Java, у вас нет шансов.

+0

FileLocks не для «блокировки внутри одной JVM» вообще. Они работают только между процессами. См. Javadoc. – EJP

+0

@EJP: Я в замешательстве: JavaDoc говорит: «Блокировки, хранящиеся в определенном файле с помощью одной виртуальной машины Java, делают не overlap._», что означает, что вы __can__ используете 'FileLock' в своей программе. Быстрая тестовая программа проверила это на Linux. С другой стороны, тот же самый док говорит: «Блоки блокировки хранятся от имени всей виртуальной машины Java. Они не подходят для контроля доступа к файлу несколькими потоками в пределах одной виртуальной машины.» «Таким образом, вы можете выбрать все, что угодно хотеть :-) –

Смежные вопросы