倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Windows のリンク、シンボリックリンクは Java nio でどう扱われるか

Windows にはリンク風のファイルとして

  • ショートカット shortcut
  • シンボリックリンク symbolic link
  • ハードリンク hardlink
  • ジャンクション junction

の4つがあります。 Java nio の java.nio.file.Files クラスではファイル属性を読み取るメソッドがあるので、これらのリンク風ファイルの属性がどのようになってるのか見てみます。 また、Files クラスの readAllBytes(), readAllLines() メソッドでこれらのファイル属性を読むとどうなるかもついでに試しました。 そういえば、Files#createLink() メソッドでリンクを作ると上記の4つのどれでもなさそうなリンク風ファイルが作られるようなので、これについても同様に属性読んだりします。

ファイルへのリンク

まずはファイルへリンクを張られているものを見ていきます。 ジャンクションはファイルへのリンクとしては作成できません。 以下の表で太字のファイル属性は "basic" 属性です。 それ以外のものは "dos" 属性です。 詳しくは『これからの「Java I/O」の話をしようwww (7) : Files クラスのメソッド 〜続・ファイル、ディレクトリの属性〜 - 倭マン's BLOG』参照。 全てのリンク風ファイルに対して同じ値をとる、もしくは他の設定で値がかわりそうな属性(system や hidden など)は省略しています。 また、ターゲットにしているファイルはファイルサイズが2800のものです。

ファイル属性 ショートカット シンボリックリンク ハードリンク リンク
(Files#createLink())
isRegularFile true true true true
isDirectory false false false false
isSymbolicLink false true false false
archive true true true true
size 1449 2800 2800 2800
attributes 32 32 32 32
  • isSymbolicLink 属性はもちろんシンボリックリンクの場合のみ true です。
  • ショートカット以外はすべて size 属性がリンク対象のファイルサイズになっています。
  • archive 属性、attributes 属性は・・・何でしょう?

リンクの読み込み
上記のリンク風ファイルを Files クラスの readXxxx() メソッドで読み込んでみるとどうなるかも試してみました:

Files のメソッド ショートカット シンボリックリンク ハードリンク リンク
(Files)
readSymbolicLink() × リンク先のファイルのパス × ×
readAllBytes() ???
readAllLines() ×
  • 「○」は問題なくリンク先のファイル内容を読み込めます。 シンボリックリンクでも readSymbolicLink() を使わなくても readAllBytes() や readAllLines() によってリンク先のファイルの内容を読めるようです。
  • 「×」は例外を投げます。 readSymbolicLink() メソッドが投げる例外は java.nio.file.NotLinkException です。
  • ショートカットに対して readAllBytes() を使うと意味不明なバイト列が読まれますが、おそらくショートカットのリンク先やプロパティに関する情報かと思われます。 解読できればショートカットのリンク先などを読み取れるかと思います。

ディレクトリへのリンク

次はディレクトリへリンクが張られているもの。 ハードリンクと Files#createLink() によって作られるリンクはディレクトリに対しては作成できません。

ショートカット シンボリックリンク ジャンクション
isRegularFile true false false
isDirectory false true true
isSymbolicLink false true false
archive true false false
size 1326 0 0
attributes 32 16 16
  • isRegularFile 属性は、ショートカットに対してはディレクトリに張られているものでも true を返します。 つまり、ショートカットは常に(ディレクトリではなく)ファイルとして扱われます。 一方、ディレクトリに対して張られているシンボリックリンクとジャンクションはディレクトリとして扱われるので、isRegularFile 属性は false を返します(isDirectory 属性は true)。
  • size 属性は、ショートカット以外は0を返します(ディレクトリ下にファイルがあろうとも)。 ショートカットに対してはおそらくファイルへのショートカットの場合と同じです。

リンクの読み込み
ディレクトリに対してのリンクに対しても Files の readXxxx() メソッドを呼び出してみましょう:

ショートカット シンボリックリンク ジャンクション
readSymbolicLink() × リンク先のディレクトリのパス ×
readAllBytes() ??? × ×
readAllLines() × × ×

まぁ、リンク先がディレクトリなので readAllBytes(), readAllLines() じゃ内容が読めないのは仕方ないですね。 ただし、ショートカットに対して readAllBytes() を呼び出すと、ファイルに対するのと同じようにショートカットのプロパティに関するであろうバイト列が読み込まれます。

まとめ
Files クラスのメソッドは Unix 系の OS に合いそうなメソッドが多いので、Windows だとちょっと扱いづらいところがありますね。 特に Windows でリンクとして使うショートカットがあまり上手く扱えず、Files で扱えるシンボリックリンクは Windows では管理者権限が必要なのでこれまた面倒。 悩ましいところですねぇ。 ただ、そもそも Java でリンク風のファイルをどの程度扱うのか?という根本的疑問もあるんだけど(笑)
Microsoft Windows 10 Home (32bit/64bit 日本語版) [オンラインコード]【新価格版】

Microsoft Windows 10 Home (32bit/64bit 日本語版) [オンラインコード]【新価格版】

Windows 10完全制覇パーフェクト

Windows 10完全制覇パーフェクト