ファイル共有(SMB)を利用するには

◆PROCESSING 逆引きリファレンス

 カテゴリー:ファイル操作

ファイル共有(SMB)を利用するには

【概要】

WindowsやLinuxでは、ファイル共有をサポートしています。

WindowsとLinux、あるいはWindows同士のファイル共有には、通常はSambaが利用されます。WindowsではSMB(Server Message Block)ですね。

PROCESSINGでは残念ながら、標準でSMBを利用したファイル共有エリアへのアクセスは行なえません。しかしPROCESSINGにJava用のライブラリを追加する事で、これを実現することが可能となります。

SMBにはSMB1(Samba3.4以前)、SMB2、SMB3と、2019年11月現在3つの大きなバージョンが存在します。

参考URL:@IT様:第7回 ファイル共有プロトコルSMBの概要

Windowsでは長らく互換性維持のために、新しいOSでもSMB1を利用する事が可能でしたが、Windows10では、ついにデフォルト状態でSMB1の利用ができなくなりました。

JavaからSMBを利用するライブラリとして有名なものにjCIFS(Java CIFS Client Library)があります。

古くからある有名なライブラリであるため、今でもネットを検索するとjCIFSのサンプルや事例が多く見つかります。

ところがこのjCIFSは、SMB1のみをサポートしています。公式サイトにも「jCIFS does not support the newer SMB2/3 variants of the SMB protocol」とある通り、SMB2/SMB3はサポートされていません。

つまりファイル共有を提供するホストがWindows10などの場合、デフォルトではjCIFS を使ってファイル共有エリアにアクセスすることができなくなりました。

jCIFSに代わるSMB2/SMB3をサポートするライブラリには

などがあります。

※ 2019/12現在、smbj はSMB3をサポートしていません。SMB2のみになります。

今回は jCIFSの後継となるjcifs-ngを利用して、ファイル共有エリアにアクセスする方法を紹介したいと思います。

 

【詳細】

最新のライブラリを入手する

EclipseやIntelliJ  Ideaを利用している人は、jcifs-ngのライブラリを Mavn Repository からGradleやMaven経由で入手するのが便利です。

jcifs-ngは、2019年12月現在Version 2.1.3 が公開されています。


標準エディタを利用している人は、jarファイルを自力で探し出すか、git-hubに公開されているソースを元にコンパイルして作成します。

例えばjarファイルがダウンロードできるサイトとしては、jar-download.com 様などがあります。自己責任でダウンロードしてください。

jcifs-ngの動作には以下のライブラリも必要となるため、合わせて入手しておきましょう。

最後の「slf4j-simple」は入手しなくても動作しますが、ライブラリがない状態で実行するとコンソール領域に警告MSGが表示されてしまいます。

 

PROCESSINGで利用できるようにする

まずPROCESSINGの標準エディタから「新規プロジェクト」を作成し、空で良いので一度保存します。

なお保存前に「ファイル→設定」で、スケッチブックの場所に「わかりやすいパス」が指定されている事を確認してください。


上記例なら、スケッチを保存すると「D:\processing-3.5.3\src」に「sketch_191123a」などのフォルダが作成され、空のプログラムソースファイルができあがります。

このフォルダ(D:\processing-3.5.3\src\sketch_191123a)配下に、code フォルダを作成してください。


続いて、上記でダウンロードした jarファイルを、code フォルダの中に複写します。

これでライブラリの準備は完了です。標準エディタを開いている人は、一度PROCESSINGを終了して、標準エディタを再起動してください。

 

ファイル共有サーバを準備する

ファイル共有を行うわけですから、共有エリアを提供してくれるサーバが必要ですね。

以下の解説では、Windows10(MSLABO-PC)をファイル共有サーバとし、その共有エリアが share という名前で公開されている前提とします。またshareにはgirl.jpg、boy.pngという画像ファイルと、SubFolderという名前のフォルダがあるものとします。

(画像URL:illust-AC 様:わことさん、猫島商会さん)

ファイル共有エリアへのアクセスには

  • 接続先ホストのアドレス
  • ユーザ名
  • パスワード

が必要となります。事前に用意をしておいてください。(※IPアドレス、またはドメイン名)

jcifs-ngでは、匿名(anonymous)にてファイル共有エリアにアクセスする事も可能なようですが、手元の環境では何故かエラーとなり成功しませんでした。

よって、ファイル共有サーバを自分で用意する場合には、該当OS上に、ファイル共有を許可するユーザとパスワードの準備もしておく必要があります。

 

接続情報を準備する

ファイル共有エリアを利用するには、認証情報を作成し、該当サーバの共有エリアに接続する必要があります。

jcifs-ngでは、サーバに接続するために

  • 認証情報(NtlmPasswordAuthenticator)
  • 基本コンテキスト(BaseContext)
  • 接続コンテキスト(CIFSContext)

の各情報を作成します。

 

認証情報を作成する

認証情報を作成するNtlmPasswordAuthenticator auth = new NtlmPasswordAuthenticator( String userName, String passWord );
auth:認証情報
userName:ユーザ名
passWord:パスワード

ユーザ名とパスワードを指定して認証情報を作成します。パスワードなしのユーザは許可されませんので、注意してください。

こんな感じで利用します。

 

基本コンテキストを作成する

基本コンテキストを作成するBaseContext bc = new BaseContext(Configuration config);

bc:基本コンテキスト
config:接続パラメータ

共有エリアに接続するための基本となるコンテキスト情報を作成します。作成するためには、接続用のパラメータを定義したConfigurationクラスを実装したインスタンス(config)が必要となります。

jcifs-ngで用いるConfigurationクラスを実装したクラスには、PropertyConfigurationクラスがあります。

.

プロパティを作成するPropertyConfiguration pc = new PropertyConfiguration(Properties p);

pc:Configurationクラスを実装したクラス
p:Javaのプロパティクラス

PropertyConfigurationのインスタンスを作成するためには、Javaのプロパティクラスを利用します。

あらかじめJavaのPropertyクラスに接続に必要となるパラメータをセットしておき、PropertyConfigurationクラスを作成し、出来上がったPropertyConfigurationインスタンスをBaseContextの生成に利用します。

こんな感じです。

jcifs-ng で利用する代表的なプロパティには、以下のようなものがあります。

プロパティ 説明
1 jcifs.smb.client.minVersion 利用するSMBの最小バージョン
2 jcifs.smb.client.maxVersion 利用するSMBの最大バージョン
3 jcifs.smb.client.connTimeout 接続タイムアウト値(ミリセカンド:初期値35秒)
4 jcifs.smb.client.responseTimeout SMB応答タイムアウト値(ミリセカンド:初期値30秒)
5 jcifs.smb.client.enableSMB2 SMB2/3を利用するか否か。初期値はtrue
6 jcifs.smb.client.disableSMB1 SMB1を利用するか否か。初期値はfalse

この他にも多数、利用可能なプロパティがあります。詳しくは公式ドキュメントを参照してください。

利用するSMBのバージョンには、以下の範囲の文字列から指定を行うことが可能です。

指定可能な値 説明
1 SMB1 SMB1を利用する
2 SMB202 SMB 2.02を利用する(Windows Vista以降)
3 SMB210 SMB 2.1を利用する(Windows 7/Server 2008R2)
4 SMB300 SMB 3.0を利用する(Windows 8/Server 2012)
5 SMB302 SMB 3.0.2を利用する(Windows 8.1/Server 2012R2)
6 SMB311 SMB 3.1.1を利用する(Windows 10/Server 2016)

 

接続コンテキストを作成する

接続コンテキストを作成するCIFSContext cifsCon = baseContext.withCredentials(NtlmPasswordAuthenticator auth);

baseContext:基本コンテキスト
auth:認証情報
cifsCon:作成された接続用のコンテキスト

上記で作成した基本コンテキストがもつメソッドに認証情報を与えることで、接続用のコンテキストを作成します。

一連の流れをコーディングすると、こんな感じになります。

 

接続する

ファイル共有エリアに接続するには、上記で作成した接続用のコンテキストと接続先情報を用いて、SmbFileクラスのインスタンスを作成する事で実現します。

接続するSmbFile sf = SmbFile(String url, CIFSContext ct);

sf:SmbFile インスタンス
url:接続先(ファイル共有サーバ)情報
ct:接続用のコンテキスト

接続に失敗するとMalformedURLException例外が発生します。

接続先となるサーバーの代表的な指定方法は、以下の書式になります。


¥記号はバックスラッシュ(/)に置き換えてください。

今回の例であれば、公開サーバ名はMSLABO-PC、共有フォルダ名はShareになります。

この書式以外にも様々な書き方が可能ですので、詳しくは公式ドキュメントを参照してください。

接続できたらSmbFile クラスのインスタンスを用いて、ファイル共有エリアの操作を行います。

操作が終わったあとは、SmbFile クラスのclose()メソッドで資源を開放しておきましょう。
.

資源を開放するvoid sf.close();

sf:SmbFile インスタンス

接続処理部分だけを書き出すと、上記のようになります。

 

ファイル一覧を取得する

それでは共有エリアにあるファイル一覧を表示してみましょう。

接続した共有エリアにあるファイル一覧は、SmbFileクラスのlistFiles()メソッドで取得します。

listFiles()には、一覧化したいファイルの条件を指定可能です。

ファイル一覧を取得SmbFile[] list = sf.listFiles(String wildcard);

sf:SmbFile インスタンス
list :得られたファイル一覧
wildcard:収集条件(例:”*.png”なら拡張子がpngのものだけを集める)

得られたファイル一覧はSmbFileの配列で戻されます。特に条件を指定しない場合、一覧はファイル・フォルダに関係なく集められます。

収集された情報がファイルなのかフォルダなのかを識別するためには、wildcardで適切な条件を指定するか、収集された情報から判定する必要があるので注意してください。

以下は共有エリアに接続した後で、ファイル一覧を取得する例です。

<出力例>

上記サンプルでは、SmbFileクラスが持つ各メソッドで集めたファイル一覧が読み書きできるか、ファイルなのかフォルダなのかを調べています。

本例ではワイルドカードを “*” にしているので、ファイルとフォルダの両方が取得されていますが、ワイルドカードを “*.jpg”  等とすれは拡張子に jpg を持つものしか一覧化されません。

プログラムの全体像は、下記サンプルを参照してください。

 

ファイルをローカルPCに複写する

それでは共有エリアにあるファイルを、手元のPCに複写してみましょう。

接続した共有エリアにあるファイルを読み取るには、SmbFileクラスが持つopenInputStream()メソッドで、読み取り用のストリームをOPENします。

リモート側(ファイル共有エリア)にあるファイルは、SmbFileクラスが持つメソッドでアクセスするのが基本となるので注意してください。

ファイルを読み取りOPENするSmbFileInputStream is = sf.openInputStream();

sf:SmbFile インスタンス
is:読み取り専用ストリーム

得られた読み取り用ストリーム(SmbFileInputStream)はJavaのInputStreamを継承したクラスであるため、JavaのInputStreamと同じように利用できます。

OPENできない場合は、SmbException例外が発生します。

上記は共有エリアに接続した後で、共有エリアにある jpg ファイルをローカルPCのD\\tempフォルダへ複写する例です。

 

ファイルを共有エリアに複写する

それでは先ほどの例とは逆で、手元のPCにあるファイルを共有エリアに複写してみましょう。

接続した共有エリアにファイルを書き込むには、SmbFileクラスが持つopenOutputStream()メソッドで、書き込み用のストリームをOPENします。

ファイルを書き込みOPENするSmbFileOutputStream os = sf.openOutputStream();

sf:SmbFile インスタンス
os:書き込み用ストリーム

得られた書き込み用ストリーム(SmbFileOutputStream)はJavaのOutputStreamを継承したクラスであるため、JavaのOutputStreamと同じように利用できます。

上記は共有エリアに接続した後で、ローカルPCにある boy.pngファイルを共有エリアにhoge.pngとして複写する例です。

共有エリアには

のように、書き込むファイルへのUNCパスを指定して接続しているものとします。

このファイル(hoge.png)は、接続先に存在する必要はありません。なければ生成されます。

ただし上記処理ではファイルの存在を確認せずに書き込んでいるため、すでにあるファイルへ書き込みを行った場合は上書き更新される事に注意してください。

 

共有エリアのファイルを削除する

次に、共有エリアにあるファイルを削除する例を紹介します。

共有エリアにあるファイルを削除するには、対象ファイルに対してSmbFileクラスが持つdelete()メソッドを利用します。

ファイルを削除するvoid sf.delete();

sf:SmbFile インスタンス

上記は共有エリアに接続した後で、共有エリアにあるファイルを削除する例です。

共有エリアにあるファイルには

のように、削除対象ファイルへのUNCパスを指定して接続しているものとします。

対象となるファイル(本例ではboy.png)が存在しない場合は、delete()時に例外エラーとなるので注意してください。

 

【関連記事】

  • なし

 


サンプルプログラム

ファイル一覧を取得する例:

MSLABO-PCという名前のファイル共有サーバにある share 領域に接続し、その中にあるjpgという拡張子を持つファイルの一覧を取得する例です。

今回の例であれば、girl.jpg がヒットします。

<出力サンプル>

 

共有エリアのファイルを取得する例:

共有エリアにあるファイルをローカルPCに複写します。

今回の例であれば、boy.png と girl.jpg がDドライブのtempフォルダにコピーされます。

<出力サンプル>

 

共有エリアへファイルを書き込む例:

ローカルエリアにある boy.png を共有エリアにhoge.pngとして複写します。

<出力サンプル>

 

共有エリアのファイルを削除する例:

共有エリアにあるファイルを削除します。本例では boy.pngとgirl.jpgが削除されます。

<出力サンプル>

 


PROCESSING逆引きリファレンス一覧 へ戻る

本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。