TL;DR
Windowsサポートするならjava.nio.file.Files.isWritable
使っといたほうが良い。
はじめに
意外とインターネットに知見がなかったので自分用メモ。
Java/Kotlinでファイルの保存処理、特にユーザーにディレクトリを選択させて保存するような処理が対象です。
Javaのクラスの話ですが自分が実際にやったのはKotlinなのでサンプルソースはそれに準じます。
書き込み権限チェックのやり方
チェック方法が2通りあります。
古いやり方と比較的新しいやり方。
java.io.File.canWrite
java.nio.file.Files.isWritable
1.は古き良きjava.io.File
クラスのインスタンスメソッド。
2.はjava.nio.file.Files
というJava 1.7で追加された比較的新しいクラスのstaticメソッド。
というかそもそもjava.nio.file.Files
クラスはstaticメソッドだけを扱っている。
Windows向きには2.を使っておいた方が何かと安全という話。
詳細をこれから説明します。
java.io.File.canWrite
繰り返すけれどこちらはインスタンスメソッド。
以下サンプル。
val file = File("任意のファイルパス")
val canWrite = file.canWrite() //書き込み可能であればtrue
とっても簡単。
これはファイルに書き込み可能属性が付与されているかだけを見ています。
Linux系だといわゆるLinuxパーミッション、Windowsで言えばファイルプロパティの読み取り専用属性が対象。
つまり実行中のJavaプロセスがOSに対して権限を持っているかまではチェックできない。
もっと言うとWindowsのUACによる権限チェックまではサポートしてくれない。
そのため、Cドライブ直下などのOS管理者権限がないと書き込めないディレクトリだと、canWrite
がtrueだったとしてもファイル書き出し時にIOException
が容赦なく投げられてしまい、はい、障害です(Javaプロセスが管理者権限で動いていればもちろんこの限りではないですが)
java.nio.file.Files.isWritable
そこで出番になるのがこちらのメソッド。
書き方はこんな感じ。
val file = File("任意のファイルパス")
val canWrite = Files.isWritable(file.toPath()) //書き込み可能であればtrue
こちらはJavaプロセスが書き込み可能な権限を持っているかを含めてチェックしてくれる。
以下はOracleJDKのドキュメントからの引用。
https://docs.oracle.com/javase/jp/8/docs/api/java/nio/file/Files.html#isWritable-java.nio.file.Path-
このメソッドは、ファイルが存在することと、このJava仮想マシンに、そのファイルを書込み用に開けるようにする適切な特権があることを確認します。
というわけなので、こちらであればUACも含めたチェックが可能。
ちなみに読み取り権限や実行権限はisReadable
やisExecutable
といったメソッドで同じようにチェック可能です。
以上です
自分が調べた限りだと、UAC関連はVista時代のインストーラーで困った系の記事しかなくて、マジでOracleのリファレンス以外に情報がなかった。
意外とここで詰まることってないのかな?
というかネイティブアプリの事例がそもそも少ないのか??
同じ事象で詰まった人の助けになれば幸いです。