0
0

More than 3 years have passed since last update.

WindowsのUACでファイルの書き込みができないのをJava/Kotlinでチェックする

Last updated at Posted at 2020-08-27

TL;DR

Windowsサポートするならjava.nio.file.Files.isWritable使っといたほうが良い。

はじめに

意外とインターネットに知見がなかったので自分用メモ。

Java/Kotlinでファイルの保存処理、特にユーザーにディレクトリを選択させて保存するような処理が対象です。

Javaのクラスの話ですが自分が実際にやったのはKotlinなのでサンプルソースはそれに準じます。

書き込み権限チェックのやり方

チェック方法が2通りあります。
古いやり方と比較的新しいやり方。

  1. java.io.File.canWrite
  2. 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

繰り返すけれどこちらはインスタンスメソッド。

以下サンプル。

sample.kt
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

そこで出番になるのがこちらのメソッド。
書き方はこんな感じ。

sample.kt
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も含めたチェックが可能。
ちなみに読み取り権限や実行権限はisReadableisExecutableといったメソッドで同じようにチェック可能です。

以上です

自分が調べた限りだと、UAC関連はVista時代のインストーラーで困った系の記事しかなくて、マジでOracleのリファレンス以外に情報がなかった。
意外とここで詰まることってないのかな?
というかネイティブアプリの事例がそもそも少ないのか??

同じ事象で詰まった人の助けになれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0