2016年12月12日月曜日

ディレクトリの監視

みなさん。 こんばんは。

大変お久しぶりです。

先日はディレクトリの監視対象の登録について見ましたが、今回は登録したディレクトリの監視対象にイベントが発生した時の処理について見てみましょう。

ディレクトリの監視の登録をすると、ディレクトリの監視が開始されます。

ディレクトリの監視は、発生しているイベントを取得し、イベントに応じた処理を行うという形式で行います。

通常は、イベントを取得し続けるために、無限ループを使用します。

WatchServiceインターフェースから、発生しているイベントをまとめたWatchKeyオブジェクトを取得するには、3種類の方法があります。

takeメソッドはイベントが発生するまでブロックするメソッドです。

イベント発生までブロックするため、InterruptedException例外がスローされることがあります。

takeメソッド以外に引数なしのpollメソッドと、ひきすうとして待ち時間を指定するpollメソッドがあります。

pollメソッドはイベントが発生していない場合、nullを返します。

待ち時間を指定するpollメソッドは、イベントの発生を指定した時間だけ待ちますが、それでもイベントが発生しないばあはnullを返します。

待ち時間を指定する場合もInterruptedException例外がスローされることがあります。

WatchKeyインターフェースには、発生したイベントをリスト形式で返すpollEventsメソッドが定義されています。

イベントはWatchEventインターフェースで表されます。

そこで、拡張for文を使用して、個々のイベントに対する処理を記述していきます。

イベントの種類はWatchEventインターフェースのkindメソッドで取得できます。

kindメソッドの返り値の型は、監視の登録時に使用したWatchEvent.Kindクラスです。

こちらも実際に使用されるのはStandardWatchEventKindsクラスです。

イベントの処理を行った後、WatchKeyインターフェースのresetメソッドをコールします。

resetメソッドをコールすることで、次のイベントを扱うことが可能になります。

では、ディレクトリの監視を行ってみましょう。

// ディレクトリの監視例while(true) {       try{           // 現在発生しているキーを取得           WatchKey key = watchService.take();
           // キーからイベントを取得           for(WatchEvent<?> event : key.pollEvents()) {                if(event.kend() == StandardWatchEventKinds.OVERFLOW) {                   // イベントがオーバーフローしていまった場合                   key.reset():                   continue;                } else {                   // それ以外の場合、                   // イベントの種類と対象となるパスを出力                   System.out.println(event.kind() + " " + event.context());                }
                // キーをリセット                if(!key.reset()) {                   break;                }             }         } catch(InterruptedException ex) {             break;         }}
// ディレクトリ監視の終了watchService.close();

上記ソースは、無限ループで監視イベントを取得し続けています。

まず、takeメソッドを使用してWatchKeyオブジェクトを取得します。

そして、WatchKeyオブジェクトからWatchKeyオブジェクトを取得しています。

監視の登録時に使用しなかった定数として、OVERFLOWがあります。

これはイベントがオーバーフローを起こし、処理できていないことを示します。

ここでは、WatchKeyインターフェースのresetメソッドをコールして、リセットを行っています。

オーバーフローしているので、あふれてしまったイベントは扱えません。

OVERFLOW以外のイベントの場合、kindメソッドでイベントの種類、contextメソッドでイベントの対象となったパスを出力しています。

ディレクトリの監視を終了させる場合、WatchServiceインターフェースのcloseメソッドをコールします。

今回はディレクトリの監視について見てみました。

いままで煩雑だったファイルに関する大幅の操作がNIO2によって簡易化したのが分かりますね!

次回はJava8で導入されたラムダ式について見ていきたいと思います。

それではまた!

人気ブログランキングへ

2016年11月30日水曜日

ディレクトリの監視(監視ディレクトリの登録方法)

みなさん。 こんばんは。

今日はディレクトリの監視について見ていきましょう。

ディレクトリの監視とは、指定したディレクトリに関する変更があるかどうかチェックする機能です。

標準では、ファイルやディレクトリの作成、削除、変更の監視を行うことができます。

既存のFileクラスでは、監視機能は提供されていませんでした。

このため、定期的にファイル一覧を取得するなどして監視を行う必要がありましたが、NIO.2を使用すれば簡単に監視を行うことができます。

ディレクトリの監視を行うのはWatchServiceインターフェースです。

これはFilesSystemクラスから取得します。

WatchServiceオブジェクトを取得するのはFileSystemクラスのnewWatchServiceメソッドです。

ファイルシステムがディレクトリの監視に対応していない場合、UnsupportedOperationException例外がスローされます。

ターゲットとなるディレクトリの監視を開始するには、Pathインターフェースのregisterメソッドを使用します。

registerメソッドの第1引数がWatchServiceオブジェクト、第2引数は可変長引数で、ここにイベントの種類を列挙します。

第2引数の型はWatchEvent.Kindインターフェースです。

しかし、実際に使用されるのはWatchService.Kindインターフェースを実装したStandardWatchEventKindsクラスになります。

StandartWatchEventKindsクラスには4種類の定数が定義されていますが、registerメソッドで使用できるのは以下の3種類です。


  • ENTRY_CREATE : ファイル/ディレクトリの作成
  • ENTRY_DELETE : ファイル/ディレクトリの削除
  • ENTRY_MODIFY : ファイル/ディレクトリの更新


なお、registerメソッドの第1引数にディレクトリではないPathオブジェクトを指定すると、NotDirectoryException例外がスローされます。

では実際に監視対象となるディレクトリの登録例を見てみましょう。

// WatchServiceオブジェクトの生成
WatchService watchService = FileSystems.getDefault().newWatchService();
// 監視の対象となるディレクトリ
Path target = Paths.get(targetDirectory);
// ディレクトリの監視を登録
target.register(watchService,
                    StandardWatchEventKinds.ENTRY_CREATE,
                    StandardWatchEventKinds.ENTRY_DELETE,
                    StandardWatchEventKinds.ENTRY_MODIFY);

上記のソースでは、デフォルトのファイルシステムを使用してWatchServiceオブジェクトを取得しています。

そして、ディレクトリに対して、ENTRY_CREATE、ENTRY_DELETE、ENTRY_MODIFYの3種類の監視イベントを登録しています。

ディレクトリ監視の登録をすると、ディレクトリの監視が開始されます。

ディレクトリの監視の登録が終わったので、実際にどのようにディレクトリの監視するのかは次回に記述していきます。

今日はこの辺にしておきましょう。

それではまた!
人気ブログランキングへ

2016年11月21日月曜日

ディレクトリのコピー

みなさん。 こんばんは。

前回はファイルツリーの走査のサンプルを見ましたが、今回はもう少し役に立つサンプルとしてディレクトリのコピーについて見てみましょう。

ディレクトリのコピーを行うには、次に示す手順で行います。

  1. ディレクトリをコピーする。このとき、ディレクトリに存在するファイル/ディレクトリはコピーされない。
  2. ディレクトリに存在するファイルをコピーする。
  3. サブディレクトリが存在したら、①に戻る。サブディレクトリがなくなるまで①と②を繰り返す。
ファイルツリーの走査を使用して、この手順を実現していきます。

①はpreVisitDirectoryメソッドで処理可能です。
次の②はvisitFileメソッドで実装できます。
③に関してはwalkFileTreeメソッドの内部で制御する処理なので、実装はありません。

ということは、preVisitDirectoryメソッドとvisitFileメソッドを実装したFileVisitorオブジェクトを生成すればよいことになります。

postVisitDirectoryメソッドなどは実装する必要がないため、ここではSimpleFileVisitorクラスの匿名クラスとして実装してみます。

// ディレクトリのコピー
// コピー元のディレクトリ
Path source = Paths.get(sourceDirectory);
// コピー先のディレクトリ
Path dest = Paths.get(destDirectory);
// ファイルツリーをたどって、ファイル/ディレクトリをコピーするFileVisitor
FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
          @Override
          public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                    throws IOException {
                 // ディレクトリのコピー
                 Files.copy(dir, dest.resolve(dir), StandardCopyOption.COPY_ATTRIBUTES);
                 return FileVisitResult.CONTINUE;
          }
          @Override
          public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                     throws IOException {
                  // ファイルをコピー
          Files.copy(file, dest.resolve(file), StandardCopyOption.COPY_ATTRIBUTES);
                  return FileVisitResult.CONTINUE;
          }
};

// ディレクトリのコピーを実行!!Files.walkFileTree(source, visitor);

上記のpreVisitDirectoryでは、ディレクトリのコピーをcopyメソッドを使用して行っています。

コピー先のディレクトリ名を解決するために使用しているのが、Pathインターフェースのresolveメソッドです。

resolveメソッドはディレクトリに対するコピーはディレクトリだけをコピーし、ディレクトリにあるファイルはコピーしません。

ファイルツリーに存在するファイルに到達するとvisitFileメソッドがコールされるので、このときにファイルのコピーを行います。

このときも、resolveメソッドを使用してファイル名の解決を行っています。

今回はファイルツリーの走査をしてディレクトリのコピーをするサンプルを記述しました。

では今日はこの辺で!

人気ブログランキングへ

2016年11月17日木曜日

ファイルツリーの走査例

みなさん。 こんばんは。

前回はファイルツリーの走査の概要について記述しました。

今回は実際の実装例について見ていきましょう。

まず、FileVisitorインターフェースの匿名クラスを示します。

それぞれのメソッドはすべて、第1引数の型はPathインターフェースになります。

preVisitDirectoryメソッドとvisitFileメソッドは、第2引数の型がBasicFileAttributesクラスになります。

postVisitDirectoryメソッドとvisitFileFailedメソッドの第2引数の型はIOException例外となり、

走査中に発生した例外が引数となります。ただし、走査が正常に行われた場合、

postVisitDirectoryメソッドの第2引数の値はnullになります。

すべてのメソッドの返り値の型はFileVisitResult列挙型です。

FileVisitResult列挙型は以下の4種類の値を取ります。


  • CONTINUE
  • SKIP_SIBLINGS
  • SKIP_SUBTREE
  • TERMINATE


走査を続けるのであればCONTINUEを返します。

SKIP_SUBLINGSはディレクトリに依存するそれ以降のファイル/ディレクトリの走査をスキップするために使用します。

同様にSKIP_SUBTREEもサブツリーの走査をスキップするために使用します。

最後のTERMINATEは走査を中止させます。

// ファイルツリーを走査するFileVisitor
FileVisitor<Path> visitor = new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDIrectory(Path dir, BasicFileAttributes attrs) {
         System.out.println("Pre visit Directory; " + dir);
         return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
         System.out.println("Visit File: " + file);
         return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
         System.out.println("Post Visit Directory: " + dir);
         return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
         System.out.println("Visit File Failed: " + file);
         return FileVisitResult.TERMINATE;
}
};
// ファイルツリーの走査実行
Path path = Paths.get("alpha");
Files.walkFileTree(path, visitor);

上記のソースでは、4種類のメソッドとともに第1引数を標準出力に出力する処理だけを行っています。

これで、どのメソッドがどの順番にコールされるかわかるはずです。

visitFileFailedメソッド以外のメソッドは正常に走査が行われているので、返り値としてCONTINUEを返しています。

visitFileFailedメソッドだけは、何らかの異常が発生したことを示しているので、走査を中止するためTERMINATEを返すようにしています。

Paths.getメソッドの引数に起点のディレクトリを指定し、FilesクラスのwalkFileTreeメソッドが実際にファイルツリーの走査を行います。

今回はFileVisitorインターフェースの匿名クラスを使用しましたが、空のメソッドが定義されている
SimpleFileVisitorクラスを使用して必要なメソッドだけオーバーライドすることもできます。

今回はコンソールに出力するだけでしたが、次回はもう少し役にたつ実装例を示していきたいと思います。

それでは今日はこの辺で!

人気ブログランキングへ

2016年11月15日火曜日

ファイルツリーの走査

みなさん。 お久しぶりです。

今日はファイルツリーの走査について見てみましょう。

Filesクラスのcopyメソッドを使用してディレクトリのコピーを行う場合、

ディレクトリに存在するファイルなどはコピーされません。

ディレクトリのすべてのファイル/ディレクトリのコピーを行うにはディレクトリの構造をたどり、

ファイルツリーの末端までファイルをコピーしていく必要があります。

しかし、いままでのFileクラスではファイルツリーをたどることはできるものの、

煩雑になりがちでした。

そこで、NIO2ではデザインパターンのVisitorパターンを利用して、

ファイルツリーを走査する機能が提供されました。

ここでは、Visitorパターンについての詳細については述べませんが、簡単に動作を説明しましょう。

Visitorは、指定されたディレクトリからファイルツリーをだどっていきます。

ファイルツリーのディレクトリ/ファイルに到達するとVisitorのコールバックメソッドがコールされます。

Visitorはファイルツリーの末端までたどっていくことで、ファイルツリーの存在するすべての

ディレクトリやファイルを走査することができます。

NIO2でVisitorとして使用されるのが、java.nio.file.FileVisitorインターフェースです。

FileVisitorインターフェースには以下の4種類のメソッドが定義されています。


  • previsitDirectoryメソッド

  • postVisitDirectoryメソッド

  • visitFileメソッド

  • visitFIleFailedメソッド


preVisitDirectoryメソッドはディレクトリに入ったときにコールされるメソッドです。

preVisitDirectoryメソッドがコールされた後、そのディレクトリに存在するファイルがあると

visitFileメソッドがコールされます。

そして、ディレクトリから抜けるとき、postVisitDirectoryメソッドがコールされます。

また、ファイルツリーの走査に失敗すると、visitFileFailedメソッドがコールされます。

文章では解りづらいので、次回はこれらの実装について見ていきます。

それでは今日はこの辺で!

人気ブログランキングへ

2016年11月3日木曜日

アトリビュートの設定

みなさん。 こんばんは。

今日はファイルのアトリビュートをまとめて設定してみましょう。

設定を行うインターフェース群は、すべて java.nio.file.attribute.AttributeView インターフェースの

継承関係にあります。

ファイルやディレクトリに対するアトリビュートを設定するために使用されるのがFileAttributeView

インターフェースです。

しかし、FileAttributeViewインターフェースにはメソッドが定義されていません。

実際には、用途ごとに定義されているFileAttributeViewインターフェースのサブインターフェースを

使用します。

BasicFileAttributeViewインターフェースはOSに依存しない共通のアトリビュートを設定するための

インターフェースです。

アトリビュートの取得に使用したBasicFileAttributesインターフェースに対応しており、

BasicFileAttributesインターフェースで取得できるアトリビュートを設定することができます。

そして、OSに依存したアトリビュートの設定を行うには、Windows用のDosFileAttributeView

インターフェース、POSIXに準拠したOS用のPosixFileAttributeViewインターフェースを使用します。

それぞれDosFileAttributesインターフェース、PosixFileAttributesインターフェースに対応してます。

PosixFileAttributeViewインターフェースはBasicFileAttributeViewインターフェースだけでなく、

FileOwnerAttributeViewインターフェースも継承しています。

FileOwnerAttributeViewインターフェースはオーナを設定するためのインターフェースです。

FileOwnerAttributeViewインターフェースのサブインターフェースはもう1つ、

AclFileAttributeViewインターフェースが提供されています。

インターフェース名のACLはAccess Control List (アクセス制御リスト)の略称です。

NIO.2のACLはRFC 3350: Network File System(NFS) version4 Protocol に基づいています。

これらのインターフェースのオブジェクトを取得するには、FilesクラスのgetFileAttributeView

メソッドを使用します。

getFileAttributeViewメソッドは、第1引数の型がPathインターフェース、

第2引数の型がClassクラス、第3引数は可変長引数でLinkOption列挙型になります。

取得したいインターフェースを第2引数に指定することで、オブジェクトを取得できます。

今回はDosFileAttributeViewインターフェースとPosixFileAttributeViewインターフェースの

オブジェクトを取得して、アトリビュートを設定してみます。

BasicFileAttributeViewインターフェースは最終更新日時、最終アクセス日、作成日時を設定する

setTimeメソッドを定義しています。

同様に、DosFileAttributeViewインターフェースはファイルをリードオンリーに設定する

setReadOnlyメソッド、隠しファイルに設定するsetHiddenメソッド、アーカイブファイルに設定する

setArchiveメソッド、そしてシステムファイルに設定するsetSystemメソッドなどを定義しています。

PosixFileAttributeViewインターフェースはパーミッションを設定するsetPermissionsメソッドと

グループを設定するsetGroupメソッドを定義しています。

また、PosixFileAttributeViewインターフェースのスーパーインターフェースである

FileOwnerAttributeViewインターフェースではオーナを設定するsetOwnerメソッドを定義してます。

では、まずWindowsで複数のアトリビュートをまとめて設定してみましょう。

// 対象となるパスPath path = Paths.get("var.txt");
// Windows用のDosFileAttributeViewオブジェクトを取得DosFileAttributeView view = Files.getFileAttributeView(path, DosFileAttributeView.class);
// BasicFileAttributeViewインターフェースで定義されたメソッドlong now = System.currentTimeMillis();view.setTime(FileTime.fromMillis(now), // 最終更新日時                   FileTime.fromMillis(now), // 最終アクセス日時                   FileTime.fromMillis(now)); // 作成日時
// DosFileAttributeViewインターフェースで定義されたメソッド// システムファイルとして設定するview.setSystem(true);

setTimeメソッドは、第1引数が最終更新日時、第2引数が最終アクセス日時、第3引数が

作成日時になります。これらの値を設定しない場合は、引数にnullを指定します。

そして、trueを引数にしてsetSystemメソッドをコールすることで、

ファイルをしsてむファイルとして設定しています。

同様に、PosixFileAttributeViewインターフェースを使用して、アトリビュートを設定してみます。

// 対象となるバスPath path = Paths.get("var.txt");
// POSIX準拠OS用のPosixFileAttributeViewオブジェクトを取得PosixFileAttributeView view  = Files.getFileAttributeView(path, PosixFileAttributeView.class);
// BasicFileAttributeViewインターフェースで定義されたメソッドlong now = System.currentTimeMillis();view.setTimes(FileTime.fromMillis(now), // 最終更新日時                    FileTime.fromMillis(now); // 最終アクセス日時                    FileTime.fromMillis(now)); // 作成日時
// アカウントの情報を取得UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService();UserPrincipal owner = LookupService.loolupPrincipalByName("sakuraba");
// PosixFileAttributeViewインターフェースで定義されたメソッドview.setOwner(owner);

PosixFileAttributeViewインターフェースでは、オーナやグループを設定することができます。

オーナはUserPrincipalインターフェース、グループはGroupPrincipalインターフェースで表します。

いずれもUserPrincipalLookupServiceクラスを使用し、既存アカウントやグループから検索します。

UserPrincipalLookupServiceオブジェクトを取得するためには、

FileSystemクラスのgetUserPrincipalLookupServiceメソッドを使用します。

そして、UserPrincipalオブジェクトを検索するにはlookupPrincipalByNameメソッドを使用します。

引数は文字列でアカウント名を指定します。

GroupPricipalオブジェクトを検索するにはlookupPrincipalByGroupNameを使用します。

引数はグループ名です。

そして、得られたUserPrincipalオブジェクトをsetOwnerメソッドで指定します。

このようにAttributeViewインターフェースのサブインターフェース群を使用することで、

アトリビュートをまとめて設定することが可能です。

それでは今日はこの辺にしておきましょう。

それではまた!
人気ブログランキングへ

2016年10月26日水曜日

複数のアトリビュートの取得

みなさん。 こんばんは。

今日はファイルの複数アトリビュートの取得について見ていきましょう。

FilesクラスのgetAttributeメソッドではアトリビュートを1つずつ取得しなくてはなりません。

ファイルの作成日時と最終更新日時などの関連するアトリビュートでも、

まとめて取得することができません。

この問題はアトリビュートの取得だけでなく、設定する場合にもあてはまります。

そこで今回は複数のアトリビュートをまとめて取得する方法について見てみましょう。

取得するアトリビュートはOSごとに異なるため、3種類のインターフェースが提供されています。

BasicFileAttributesインターフェースはOSによらない、

共通のアトリビュートを取得するために使用します。

OSに依存するアトリビュートは、BasicFileAttributesインターフェースのサブインターフェースとして

定義されています。

Windows用に使用するのがDosFileAttributesインターフェース、LinuxやMac OS Xのような

POSIX準拠のOS用に使用するのがPosixFileAttributesインターフェースです。

では、これらのインターフェースを使用してアトリビュートを取得してみましょう。

取得するのはFilesクラスのreadAttributesメソッドを使用します。

readAttributesメソッドの第1引数はPathインターフェース、第2引数はClassクラスです。

第2引数でどのインターフェースを取得するかを指定します。

取得できないインターフェースを指定した場合、nullが返ります。

たとえば、WindowsでPosixFileAttributesオブジェクトを取得しようとしても、nullが返ります。

第3引数は可変長引数で、引数の型はLinkOption列挙型です。

リンクを追わないようにする場合、第3引数にNOFOLLOW_LINKSを指定します。

まず、Windowsのアトリビュートを取得してみます。

// 対象となるバス
Path path = Paths.get("var.txt");
// Windows用のDosFileAttributesオブジェクトの取得
DosFileAttributes attributes = Files.readAttributes(path, DosFileAttributeView.class);
// BasicFileAttributesインターフェースで定義されたメソッド
System.out.println("Creation Time: " + attributes.creationTime());
System.out.println("Last Modified Time: " + attributes.lastModifiedTime());
System.out.println("Last Access Time: " + attributes.lastAccessTime());
System.out.println("File: " + attributes.isRegularFile());
System.out.println("Directory; " + attributes.isDirectory()):
System.out.println("Symbolic Link: " + attributes.isSymbolicLink());
// DosFileAttributesインターフェースで定義されたメソッド
System.out.println("System File: " + attributes.isSystem());

readAttributesの第2引数にDosFileAttribute.classを指定することで、

DosFileAttributesオブジェクトを取得できます。

DosFileAttributesインターフェースでは、スーパーインターフェースのBasicFileAttributes

インターフェースで定義されたOSに共通のアトリビュートを取得するメソッドと、

Windowsだけで取得可能なアトリビュートを取得できるメソッドを使用することができます。

ファイルの作成時を取得するcreationTimeメソッドなどはBasicFileAttributesインターフェース

で定義されたメソッドです。

これに対し、isSystemメソッドがDosFileAttributesインターフェースで定義されたメソッドになります。

同様にLinuxやMac OS X のようなPOSIX準拠OSでもアトリビュートをまとめて取得してみましょう。

// 対象となるパス
Path path = Paths.get("var.txt");
// POSIX準拠OS用のPosixFileAttributesオブジェクトの取得
PosixFileAttributes attributes = Files.readAttributes(path, PosixFileAttributeView.class);
// BasicFileAttributesインターフェースで定義されたメソッド
System.out.println("Creation Time: " + attributes.creationTime());
System.out.println("Last Modified Time: " + attributes.lasoModifiedTime());
System.out.println("Last Access TIme: " + attributes.lastAccessTime());
System.out.println("File: " + attributes.isRegularFile());
System.out.println("Directory: " + attributes.isDirectory());
System.out.println("Symbolic Link: " + attributes.isSymbolicLink());
// PosixFileAttributesインターフェースで定義されたメソッド
System.out.println("Owner: " + attributes.owner());
System.out.println("Permission: " + PosixFilePermissions.toString(attributes.permissions()));

DosFileAttributesインターフェースの代わりにPosixFileAttributesインターフェースを使用

していること以外はほぼ同じです。

ファイルの属性をまとめて取得できることでプログラミングでできる幅が広がりましたね!

では今日はこの辺で!

人気ブログランキングへ

2016年10月24日月曜日

FileAttributeを使用したパーミッションの設定

みなさん。 こんばんは。

今日はパーミッションを指定してファイルを作成する方法を見ていきましょう。

FIlesクラスでファイルやリンクを作成するメソッドは、パーミッションを指定できます。

パーミッションを指定できるメソッドは以下の8種類です。


  • createFileメソッド
  • createTempFileメソッド
  • createDirectoryメソッド
  • createTempDirectoryメソッド
  • createDirectoriesメソッド
  • createLinkメソッド
  • createSymbolicLinkメソッド
  • newByteChannelメソッド

createTempFileメソッドとcreateTempDirectoryメソッドは、

一時ファイルを作成するためのメソッドです。

これらのメソッドでパーミッションを指定するために使用されるのが、

java.nio.file.attribute.FileAttributeインターフェースです。

FileAttributeインターフェースはnameメソッドとvalueメソッドを定義しており、

それぞれアトリビュート名と値を返します。

FIleAttributeインターフェースの実装クラスは提供されていませんが、

PosixFilePermissionsクラスにFIleAttributeオブジェクトを生成するasFileAttributeメソッドが

定義されています。

それでは、createFileメソッドでリードオンリーのファイルを作成してみましょう。

// 対象となるパス
Path path = Paths.get("var.txt");
// リードオンリーのパーミッションを生成
Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("r--r--r--");
// パーミッションをFileAttributeオブジェクトに変換
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(permissions);
// パーミッションを指定して、ファイルを生成
Files.createFile(path, attr);

ァイルのアトリビュートの設定が簡単に出来ましたね!

それでは今日はこの辺で!

人気ブログランキングへ

2016年10月19日水曜日

名前を指定したファイルアトリビュートの取得、設定

みなさん。 こんばんは。

今日は名前を指定したファイルアトリビュートの取得、設定方法について見ていきましょう。

アトリビュート名を指定してアトリビュートを取得するにはFilesクラスのgetAttributeメソッド

を使用します。

まず、アトリビュートの取得について見てみましょう。

// アトリビュート名を指定してアトリビュートを取得
// 対象になるパス
Path path = Paths.get("foo.txt");

// 最終変更日時を取得
FileTime lastModify = (FileTime)Files.getAttribute(path, "lastModifiedTime");

// ファイルサイズを取得
Long size = (Long)Files.getAttribute(path, "size#);

getAttributeメソッドの第1引数はPathオブジェクト、第2引数にアトリビュート名を指定します。

返り値の型がObjectクラスのため、必要に応じてキャストを行います。

また、第3引数の可変長引数になっており、列挙型のLinkOptionでリンクを追うかどうかを

指定することができます。

ここでは、OSによらず取得できるアトリビュートとして、最終更新日のLastModifiedTime、

ファイルサイズのsizeを使用しました。

OSに特有のアトリビュートを取得するには、アトリビュート名にOSを表す接頭語を付加する

必要があります。

Windowsでは"dos"、POSIX準拠のOSでは"posix"を付加します。

例えば、POSIXでオーナを取得したいのであれば、getAttributeメソッドの引数を"posix:owner"

とします。

続いてアトリビュートの設定について見てみましょう。

アトリビュートの設定はsetAttributeメソッドを使用します。

setAttributeメソッドの第1引数はPathオブジェクト、第2引数にアトリビュート名、

第3引数にその値を指定します。

getAttributeメソッドと同様に、第4引数は可変長引数で列挙型のLinkOptionを指定することが

できます。

getAttributeメソッドの返り値がObjectクラスだったのと同様に、

第3引数のアトリビュートの値を示す型もObjectクラスになります。

それではファイルアトリビュートの最終更新日を現在の時間に設定してみましょう。

// アトリビュート名を指定してアトリビュートを設定
// 対象となるパス
Path path = Paths.get("var.txt");

// 最終変更日時を現在時刻に設定
FileTime lastModify = FileTime.fromMillis(System.currentTimeMillis());
Files.setAttribute(path, "LastModifiedTime", lastModify);

FileTimeクラスはファイルのタイムスタンプ属性の値を表します。

ファイルアトリビュートの設定が簡単に出来ましたね!

それでは今日はこのへんで!

人気ブログランキングへ

2016年10月18日火曜日

ファイルアトリビュートの設定

みなさん。 こんばんは。

昨日はファイルのアトリビュートの取得について書きましたが、

今日はファイルのアトリビュート設定について見ていきましょう。

早速ファイルの最終更新日時とパーミッションを変更してみます。

最終更新日時を変更するには java.nio.file.attribute.FileTime クラスを使用します。

FileTimeクラスは、作成日時や最終更新日時などのファイルに関するタイムスタンプを

保持するクラスです。

FileTimeクラスのオブジェクトの生成には、ファクトリメソッドのfromメソッドもしくは、

fromMillisメソッドを使用します。

さっそく見てみましょう。

// Filesクラスのアトリビュート設定メソッドの使用例

// 対象となるパスPath path = Paths.get("foo.txt");
// 最終変更日時を変更FileTime time = FileTime.fromMillis(System.currentTimeMillis()):Files.setLastModifiedTime(path, time);

最終更新日時には、System.currentTimeMillisメソッドを使用して現在時刻を設定しています。

次にパーミッションの設定について見ていきましょう。

// パーミッションを変更(Windowsは不可)if(!System.getProperty("os.name").contains("Windows")) {       Set<PosixFilePermisshon> permisshons = PosixFilePermissions.fromString("rw-rw-rw-");       Files.setPosixFilePermissions(path, permissions);}

パーミッションはPosixFilePermission列挙型で表します。

ここでも、ユーティリティークラスのPosixFilePermissionsクラスが提供しているファクトリメソッドの

fromStringメソッドを使用します。

fromStringメソッドでは、UNIXでのパーミッションを表す文字列を引数に指定します。

返り値はパーミッションを表すSet<PosixFilePermissions>オブジェクトになります。

上記パーミッションロジックは、誰でも読み込み、書き込み可能な設定にしています。

今日はこの辺にしておきましょう。

それではまた!

人気ブログランキングへ

2016年10月17日月曜日

ファイルのアトリビュート取得

皆さん。 こんばんは。

今日はあいにくの雨でしたね。

最近涼しくなってきて、気温も調度よく過ごしやすくなってきました。

今日はファイルのアトリビュートについて見ていきましょう。

今までのFileクラスでは、様々なOSに共通しているアトリビュートしか扱うことが出来ませんでした。

JavaSE7/8からは、OSごとに扱えるアトリビュートを定義し、Javaが動作するOSによって

切り替えられるようにしています。

また、共通しているアトリビュートは簡単に取得できるようになっています。

それでは具体的に見ていきましょう。

// Filesクラスのアトリビュート取得メソッドの使用例
// 対象となるパス
Path path = Paths.get("var.txt");
// 最終変更日時を取得
FileTime time = FIles.getLastModifiedTime(path);
System.out.println("Last Modify: " + time);
if(!System.getProperty("os.name").contains("Windows")) {
            // パーミッションを取得(Windowsは不可)
            Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(path);
            // パーミッションをUnixの文字列表記に変換する
            System.out.println("Permissions: " + PosixFilePermissions.toString(permissions));
} else {
            // ファイルが実行可能か?
            System.out.println("Executable: " + Files.isExecutable(path));
            // ファイルが読み取り可能か?
            System.out.println("Readable: " + Files.isReadable(path));
            // ファイルが書き込み可能か?
            System.out.println("Writable: " + Files.isWritable(path));
}

PosixFilePermissionsクラスを使うことで、UNIXでおなじみの rwxrw-r-- のような

パーミッション表示への変換などを行うことができます。

取得した属性情報をもとに処理を制御するような使われ方をするでしょう。

今日はここまでにしたいと思います。

それではまた!

人気ブログランキングへ

2016年10月13日木曜日

Pathiに対する操作(簡易的な読み書きの方法)

みなさん。 こんばんは。

前回はファイルの入出力やリーダ、ライタについて述べてきましたが、

これらに加えて、Filesクラスには簡易的な読み込みメソッド及び書き込みメソッドが

提供されています。

それでは具体的に見ていきましょう。

// ファイルの内容をバイト配列で読み込む
Path path = Paths.get("test.txt");
byte[] bytes = Files.readAllBytes(path);

たった2行でバイト配列読み込みを記述出来ましたね!次にファイルの内容を文字列で読み込み

// ファイルの内容を文字列で読み込む
Path path = Paths.get("test.txt");
// ファイルの内容を1行ごとの List として読み込み
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// 読み込んだファイルの内容をコンソールに出力
for(String line: lines) {
    System.out.println(line);
}

Files.readAllLines()メソッドの第2引数では文字コードをjava.nio.charset.Charsetで指定できますが

第2引数を省略した場合はUTF-8で読み込まれます。

次に書き込みを行うメソッドを見てみましょう。

書き込みは Files.write() メソッドで、Pathが示すファイルにバイト配列または文字列を

書き出すことができます。

ファイルが存在しない場合は作成され、すでに存在する場合は上書きされます。

// バイト配列または文字列をファイルに書き出す
Path path = Paths.get("test.txt");
// バイト配列をファイルに書き出す
byte[] bytes = ・・・
Files.write(path, bytes);
// 文字列をファイルに書き出す
List<String> lines = ・・・
Files.write(path, lines, Charset.forName("UTF-8"));

なお、Files.write()メソッドの引数には java.nio.files.OpenOption を指定でき、

ファイルの書き込みモードを指定できます。

たとえば以下のようにすると、ファイルを上書きするのではなく、追記で書き込みが行われます。

Files.write(path, lines, Charset.forName("UTF-8"), StandardOpenOption.APPEND);

今日はこのへんにしておきましょう。

それでは、また!

人気ブログランキングへ

2016年10月12日水曜日

Pathの機能(ファイルリーダ、ライタ)

みなさん。 こんばんは。

昨日はファイルの入出力について書きましたが、今日はファイルのリーダ、

ライタについて書いていきます。

まずJavaSE6までのリーダ、ライタについて見ていき、次に最新の手法について見ていきましょう。

// ファイルの内容を文字列で読み込む
try(BufferedReader reader = new BufferedReader(
     new InputStreamReader(new FileInputStream("sample.txt"), "UTF-8"))) {
 
     String line = null;
     // ファイルの内容を1行ずつ読み込んでコンソールに出力する
     while((line = reader.readLine()) != null) {
          System.out.prinltn(line);
     }
}

// ファイルに文字列を書き出す
try(BufferedWriter writer = new BufferedWriter(
     new OutputStreamWriter(new FileOutputStream("test.txt"), "UTF-8"))) {
      // ファイルに文字列を書き出す
     writer.write("ファイルに文字列を出力");
      // ファウルに改行を出力
     writer.newLine();
}

次にJavaSE7/8でのリーダについて見ていきましょう。

JavaSE7/8でのリーダの取得はFiles.newBufferedReader()メソッドを使います。

// 読み込むファイル
Path path = Paths.get(filename);
// newBufferedReaderメソッドを使用して、BufferedReaderオブジェクトを取得
try(BufferedReader reader = Files.newBufferedReader(path)) {
     List<String> list = new ArrayList<>();
    for(;;) {
           String line = reader.readLine();
           if(line != null) {
              list.add(line);
           } else {
              break;
           }
    }
} catch (IOException ex) {
     // 例外処理
}

感想としてファイルの読み込み書き込みとも、JavaSE 7/8 で記述量が若干減ったかなという

印象です。

まだJavaSE7/8でのライブラリ対応がされていない場合は従来のJavaSE6でのリーダ、ライタ

を使うと良いでしょう。

それではまた!

人気ブログランキングへ

2016年10月11日火曜日

Pathの機能(ファイルの入出力)

みなさん。 こんばんは。

今日はJava SE 7/8 でのファイルの入出力について見ていきます。

Java SE 7/8 では Files.newInputStream()メソッド、Files.newOutputStream()メソッド、

Files.newByteChannel()メソッドで、それぞれPathが示すファイルに対するInputStream、

OutputStream、ByteChannelが取得できます。

では具体的に見ていきましょう。

// Pathから入出力ストリームを取得する
Path path = Paths.get("C:/Users/test.txt");
// InputStreamを取得
InputStream in = Files.newInputStream(path);
// OutputStreamを取得
OutputStream out = Files.newOutputStream(path);
// ByteChannelを取得
ByteChannel channel = Files.newByteChannel(path);

ストリームを取得した後は読み込みや書き込みの処理に移ります。

メソッド名が具体的で分かりやすいですね!

これらのメソッドには第2引数以降に java.nio.file.OpenOption を渡すことで、

オープンモードを指定できます。OpenOptionは、java.nio.file.StandardOpenOptionという

enumで指定します。

// オープンモードを指定する
import static java.nio.file.StandardOpenOption.*;
// (APPENDオプション)すでに存在するファイルを追記モードでオープンする
OutputStream out1 = Files.newOutputStream(path, APPEND);
// (CREATEオプション) 存在しない場合は新規作成
OutputStream out2 = Files.newOutputStream(path, CREATE, APPEND);
// (CREATE_NEWオプション)ファイルを作成し書き込みモードでオープン。すでにファイルが存在する場合は例外をスローする
OutputStream out3 = Files.newOutputStream(path, CREATE_NEW);

OpenOptionとして指定可能は値はほかにもあります。

今日はファイルの入出力について書いていきました。


人気ブログランキングへ

2016年10月6日木曜日

Pathの機能(リンクの作成)

みなさん。 こんばんは。

今日はリンクの作成について見ていきましょう。

リンクの作成はJavaSE 6までは出来ませんでした。

JavaSE 7/8 からリンクの作成が出来るようになりました。

これからは、ハードリンクやシンボリックリンクを作成する際に困ることも無いですね。

File.coreateLink()メソッドでハードリンクを、File.createSymbolicLink()メソッドで

シンボリックリンクを作成出来ます。

プラットフォームがこれらの機能をサポートしていない場合は UnsupportedOperationExceptionを、

すでにファイル等が存在するためリンクを作成できない場合は FileAlreadyExstsExceptionを

スローします。

それでは具体的なソースを見てみましょう。

// ハードリンクを作成する
Path path = Paths.get("doc", "readme.txt");
Path link = Paths.get("link.txt");
// doc/readme.txtのハードリンクをlink.txtとして作成
Files.createLink(link, path);

File.createSymbolicLink()メソッドには、第3引数以降に作成するシンボリックリンクの属性を

FIleAttributeで指定できます。

// シンボリックリンクを作成する
Path path = Paths.get("doc", "readme.txt");
Path link = Paths.get("link.txt");
// doc/readme.txtのシンボリックリンクをlink.txtとして作成
Files.createSymbolicLink(link, path);

Windows環境でFiles.createSymbolicLink()メソッドを呼び出すと、例外が発生します。

この場合は、Java VM を管理者モードで実行する必要があるそうです。

今日はここまでにしておきましょう。

それではまた!

人気ブログランキングへ

2016年10月5日水曜日

Pathの機能(ファイル/ディレクトリの作成)

みなさん。 こんばんは。

今日はファイルやディレクトリの作成方法について見ていきましょう。

従来のJavaSE6までのファイルやディレクトリの作成はFileクラスで生成していました。

// ディレクトリの作成
File dir = new File("dir");
dir.mkdir();
// ファイルの作成
File file = new File(dir, "test.txt");

JavaSE 7/8 からはFilesクラスのcreateFileメソッドを使用します。

// ディレクトリの作成
Path dir = Paths.get("dir");
Files.createDirectory(dir);
// ファイルを作成
Path file = dir.resolve("test.txt");
Files.createFile(file);

ファイルは作成しただけなので、ファイルの中身は何もなく、サイズは0バイトです。

もし、作成するファイルやディレクトリと同名のファイルもしくはディレクトリが存在している場合は、

FileAlreadyExistsException例外がスローされます。

また、何らかのエラーが発生した場合は IOException例外がスローされます。

書き込み権限がない場合は SecurityException例外がスローされます。

もし、複数のディレクトリを作成する場合は、 createDirectoriesメソッドを使用します。

// 複数のディレクトリを作成
Path path = Paths.get("foo/bar/baz");
Files.createDirectories(path);

createDirectoryメソッドとは異なり、createDirectoriesメソッドは同名のディレクトリが、

存在していても FileAlreadyException 例外はスローされません。

ただし、同名のファイルが存在していた場合はFileAlreadyExistsException例外がスローされます。

それでは今日はこの辺にしておきましょう!

人気ブログランキングへ

2016年10月4日火曜日

Pathの機能(ファイルの削除)

みなさん。 こんばんは。

今日はJava SE 7/8 でのファイルの削除について見ていきましょう。

Java SE 6 までのファイル削除はFileクラスのdeleteメソッドを使っていました。

Java SE 7/8 からは削除対象ファイルのパスを生成しFilesクラスのdeleteメソッドを使用します。

詳しく見てみましょう。

// 削除対象ファイル
Path path = Paths.get("C:/Users/var.txt");
// 削除
Files.delete(path);

尚、削除対象が存在しない場合は、java.nio.file.NoSuchFileExceptionがスローされ、

書き込み権限が無い場合は、SecurityExceptionがスローされます。

その他の例外はIOExceptionがスローされます。

また、削除対象が存在するかどうかチェックを行い、存在する場合のみ削除を行う

deleteIfExistsメソッドがあります。

ディレクトリの削除は、ディレクトリが空の場合のみ削除可能で、もし、ファイルが存在する場合は

java.nio.file.DirectoryNoEmptyExceptionがスローされます。

空では無いディレクトリを削除するには、ファイルのツリーをたどり、最も階層の深いファイルから

順々に削除してファイルの削除が終わってからディレクトリを削除します。

ディレクトリを再帰的に削除していく方法はまた今度見ていきましょう。

それではまた!
人気ブログランキングへ

2016年10月3日月曜日

Pathの機能(ファイルやディレクトリの移動)

みなさん。 こんばんは。

今日はファイルやディレクトリの移動について見ていきましょう。

ファイルやディレクトリの移動はJavaSE6のFileクラスでは出来ませんでした。

JavaSE7以降からはFilesクラスのmoveメソッドを使用してファイルやディレクトリの移動をします。

例を見てみましょう。

// 移動元のファイル名
Path form = Paths.get("C:/Users/hoge.txt");
// 移動先のファイル
Path to = Paths.get("C:/Users/tmp/hoge.txt");
// hoge.txtをtmp/hoge.txtに移動
Files.move(from, to);

はい。簡単ですね!

また、移動先のファイルやディレクトリがすでに存在する場合、

FileAlreadyExistsExceptionがスローされるようです。

それを回避するために、以下のように第3引数にCopyOption#REPLACE_EXISTINGオプションを

指定することにより上書きできます。

// 移動先のファイルを上書きする
Files.move(from, to, CopyOption.REPLACE_EXISTING);

またファイルやディレクトリの名前の変更も、Files.moveメソッドを使います。

// 元のファイル名
Path src = Paths.get("foo.txt");
// 変更後のファイル名
Path dest = Paths.get("bar.txt");
// ファイル名を変更
Files.move(src, dest);

JavaSE 7/8 ではファイルやディレクトリの移動が出来るようになって便利になりましたね。

それではまた!

人気ブログランキングへ

2016年10月1日土曜日

Pathの機能(ファイルのコピー) 

みなさん。 こんにちは。

今日はJavaSE 7/8 のファイルコピーについて書いていきます。

今までのファイルのコピーは、コピー元のファイルを読み込んで、コピー先のファイルに書き込む

という入出力の処理を記述する必要がありました。

Java6までのファイルコピー例

     //Fileオブジェクトを生成する
            FileInputStream fis = new FileInputStream("c:\\image001.jpg");
            FileOutputStream fos = new FileOutputStream("c:\\image002.jpg");

            //入力ファイルをそのまま出力ファイルに書き出す
            byte buf[] = new byte[256];
            int len;
            while ((len = fis.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

JavaSE7/8のファイルコピー例

     // 先ずはPathオブジェクトの生成
     Path from = Paths.get("C:/Users/hoge.txt");
     Path to = Paths.get("C:/Users/fuga.txt");

     // Filesクラスのコピーメソッドでhoge.txtをfuga.txtにコピー
     Files.copy(from, to);


移動先のファイルやディレクトリが既に存在する場合、FileAlreadyExistsExceptionが

スローされます。

その場合、coypメソッドの第3引数にCopyOption.REPLACE_EXISTING オプションを
指定することでファイルを上書きコピーすることができます。

     // 移動先のファイルを上書きする
     Files.copy(from, to, CopyOption.REPLACE_EXISTING);

他に第3引数に指定可能なオプションは以下のものがあります。

COPY_ATTRIBUTES : ファイル、ディレクトリの属性をコピー先に引き継ぐ
NOFOLLOW_LINK : シンボリックリンクをたどらずに、シンボリックリンクそのものをコピーする

感想としてファイルのコピー記述が簡単になったのと、Linuxなどのシンボリックリンクのコピーに

対応していたり、機能が強化された印象です。


人気ブログランキングへ

2016年9月29日木曜日

Pathの機能(Pathとファイルの相互変換)

みなさん。 こんばんは。

今日はPathとFileの相互変換について見ていきましょう。

Java7よりPathインターフェース機能が導入されても、Fileクラスしかライブラリが対応していない

ことはよくあることです。

そのため、PathオブジェクトとFileオブジェクトが相互変換しないといけないニーズがあります。

ではさっそくどんな感じか見てみましょう。

// Pathオブジェクトの生成
Path path = Paths.get("C:/Users/var.txt"); 

// PathオブジェクトからFileオブジェクトへの変換
File file = path.toFile();

// FileオブジェクトからPathオブジェクトへの変換
Path path_file = file.toPath();
if'( path.equals(path_file) ) {
          System.out.println("同じです");
}else{
          System.out.println("違います");
}



toFile()メソッドでFileオブジェクトに変換、toPath()メソッドでPathオブジェクトに変換できます。

変換したFileオブジェクトで対応するライブラリで使用できます。

人気ブログランキングへ

2016年9月28日水曜日

Pathの機能(親ディレクトリの取得)

みなさん。 こんばんは。

機能はPathの機能で絶対パスに変換と、パスの正規化について見てみました。

今日は指定したPathの親ディレクトリを取得する機能を見ていきましょう。

JavaSE6での親ディレクトリの取得方法

File file = new File("C:\Users\\kumeda\\test.txt");
// 親ディレクトリの取得
String parentDirName = file.getParent(); // C:\Users\kumeda
// 親ディレクトリを表すFileオブジェクトの取得
File parentFileDir = file.getParentFile(); // C:\Users\kumeda

Path機能を利用した親ディレクトリの取得

Path path = Paths.get("C:\Users\\kumeda\\test.txt");
// 親パスの取得
Path parentPath = path.getParent(); // C:\Users\kumeda
// リートパスの取得
Path rootPath = path.getRoot(); // C:\

getParent()メソッドやgetRoot()メソッドなど名前からどんな機能か分かりやすいですね。

親ディレクトリを取得する処理は色んな場面で使われそうですね。

明日はPathとFileの相互変換について書いていきます。

それではまた☆


人気ブログランキングへ

2016年9月27日火曜日

Pathの機能(絶対パス取得)

みなさん。こんばんは。

今日はJavaSE7から導入されたPathインターフェースの絶対パス取得について

JavaSE6の方法と比較しながら見てきましょう。

まず相対パスから絶対パスに変換する処理
今までのJavaSE6の絶対パスの取得方法は

File file = new File("var.txt"); // ファイルオブジェクトの生成
String absolutePath = file.getAbsolutePath(); // 絶対パスの取得

JavaSE7のパスインターフェースの機能を使い絶対パスを取得する方法は

Path path = Paths.get("var.txt"); // パスオブジェクトの生成
Path absolutePath = path.toAbsolutePath();

なお、カレントディレクトリを表す "." や親ディレクトリを表す ".." を含む場合、

以下のように記述することでパスを正規化できます。

JavaSE6

File file = new File("C:\\Users\\kume\\..\\test.txt");
String path = file.getCanonicalPath(); // 正規化したパスを取得
System.out.println(path); // C:\Users\test.txt
File normalized = file.getCanonicalFile(); // C:\Users\test.txt

JavaSE7

Path path = Paths.get(".var.txt");
path = path.normalize(); // normalizeメソッドは冗長なパスを簡潔にするメソッド
Path absolutePath = path.toAbsolutePath(); // 絶対パスに変換
System.out.println(absolutePath); // C:\Users\var.txt

normalize()メソッドを経ずに絶対パスに変換した場合、「C:\Users\.\var.txt」と表示されます。

今日はここまでにしておきましょう。

明日もPathインターフェース機能の続きを見てみます。


人気ブログランキングへ

2016年9月26日月曜日

新しいファイルシステム

みなさん。 こんばんは。

今日は新しいファイルシステムについて書いていきます。

java SE 6まではファイルを表すクラスはFileクラスを使用していましたが、Java SE 7からは

java.nio.file.Pathインターフェースを使用するようになりました。

今までのファイル生成は

File file = new File("C:/src/var.txt");

にて生成していきましたが、


これからは

Path path = Paths.get("C:/src/var.txt");

でPathオブジェクトを生成します。

Pathオブジェクトの機能についてはこれからまた書いていきますね。


人気ブログランキングへ

2016年9月17日土曜日

java資格試験の勉強

みなさん こんにちは。
今日は資格試験について書いていきます。
よくjavaの開発者は資格試験はあまり役に立たないと言います。
本当にそうでしょうか?
資格試験はどちらかというと、理論に関する試験で、実務は実際のコーディングです。
でも理論が分かってないと、実際、どのようにコーディングしていったら良いか?とか、バグが出たときに、例えば、javaのtry with resources 文が内部的にどのように動作してるか分からずにデバッグに時間がかかったりと、著しく生産性が下がったりします。
自分は実務でコーディングしていますが、資格試験の問題を解いてみると、間違いが多く、いかに理論が分かってないかと言うことを認識させられました。
生産性を上げるためには、資格試験は効率の良い学習法であると感じました。

人気ブログランキングへ

2016年9月16日金曜日

リソースの自動クローズ

みなさん。 こんばんは。

今日はリソースの自動クローズを読みました。

今までのリソースのクローズは煩雑でコードが読みづらかったですが、

Java SE 7で導入されたtry with resources文で簡潔に書けるようになりました。

またtry with resources構文を使用すると、ファイルなどのリソースのクローズ処理を

自動で行ってくれます。

今までのサンプルソース

public class ReadSample {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            // リソースのオープン
            // リソースの処理
        } catch (FileNotFoundException e) {
            // 例外処理
        } catch (IOException e) {
            // 例外処理
        } finally {
        // クローズ処理
            if (br != null)
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

クローズ処理が煩雑ですね。

try with resources文

try (// リソースのオープン) {
            // リソースの処理
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

クローズ処理が無くなって随分簡潔になりましたね。

明日から帰省の関係で読書が出来ませんが、なるべく更新していきたいと思います。

人気ブログランキングへ

2016年9月14日水曜日

ジェネリクス型パラメータの省略

みなさん。 こんばんは。

今日は第1章「小さな言語使用の変更」の「ジェネリクス型パラメータの省略」を読みました。

従来のジェネリクスを使用したクラスのオブジェクトを生成する場合

List<String> list = new ArrayList<String>();

上記のように左右2か所に型パラメータを記述していました。

JavaSE 7 からこのように簡潔に書けるようになりました。 

List<String> list = new ArrayList<>(); // 右辺の型パラメータの省略

この機能は、インスタンスへの参照を保持する変数がどのような型変数で宣言しているかを

コンパイラが判断し、同じ型を使ってインスタンス生成時の型変数を決定するというものです。

このような機能を「型推論」と呼びます。

型パラメータの省略が使える箇所
・変数の初期化   List<Integer> list = new ArrayList<>():
・三項演算子       List<String> list = flg ? new ArrayList<>(); : new LinkedList<>():
・メソッドの引数    String result = getResult(new ArrayList<>());
・メソッドの戻り値  List<String> getResultList(){ return new ArrayList<>(); }
・仮型パラメータを使用した変数への代入
public class Generics<T> {
private List<T> list;
public Generics() {
list = new ArrayList<>();
}

型パラメータの省略が使えない箇所
・匿名クラス

Callable<String> call = new Callable<> { ,,,} // コンパイルエラー

感想として実装するときに記述が少なくなるのは良いですが、慣れないうちは従来のジェネリクス

を使用したオブジェクト生成になってしまいそう。。



人気ブログランキングへ

2016年9月13日火曜日

適切な型による例外の再スロー

みなさん。 こんばんは。

今日は第1章「小さな言語使用の変更」の「適切な型による例外の再スロー」を読みました。

前日はマルチキャッチについて書きましたが、適切な型による例外の再スローは、

マルチキャッチを行わずにExceptionでキャッチして、再スロー出来るようになりました。

JavaSE6まではthrowsに記述した例外の型とthrowの例外の型が一致していないと

コンパイルエラーになっていましたが、JavaSE7以降はException型を適切な型に変換します

さっそくどんな内容かソースを見てみましょう。

// 適切な型による例外の再スロー
public void rethrowException(String exceptionName)
  throws FirstException, SecondException { // 何の例外をスローするか指定
    try {
      // ...
    }
    catch (Exception e) { // マルチキャッチを使わずにExceptionでキャッチ
      throw e; // コンパイラは FirstException または SecondException のインスタンスであると判断する
    }
  }

Project Coinではマルチキャッチを使わずにExceptionでキャッチして再スロー出来るので、

より簡潔な記述が出来ますね。

人気ブログランキングへ

2016年9月12日月曜日

マルチキャッチ

みなさん。 こんばんは。

今日は第1章「小さな言語使用の変更」のマルチキャッチを読みました。

・マルチキャッチ

javaSE7よりも前のバージョンでは、例外の種類ごとにcatchブロックを用意して、

例外処理を記述していました。

この方法では同じ例外処理を複数のcatchブロックに記述しなければいけないため、

煩雑なコードになりがちでした。そこで、

」avaSE7から複数の例外を1つのcatchブロックでキャッチできるマルチキャッチが導入されました。

これにより、異なる例外に対して同じ処理となる例外処理は、1つのcatchブロックにまとめることが

できるようになります。

ではソースコードを書いてみましょう。

public class MaltiCatchTest {

public static void main(String[] args) {
String param = args.length > 0 ? args[0] : "a";
try {
new MaltiCatchTest().testException(param);
System.out.println("end");
} catch (SampleAException | SampleBException e) { // 例外処理を一つにまとめる。
System.out.println("Exception Result " + e);
}
}

public void testException(String param) throws SampleAException, SampleBException{
switch (param) {
case "a":
throw new SampleAException();
case "b":
throw new SampleBException();
default :
break;
}
}

class SampleAException extends Exception {

}

class SampleBException extends Exception {

}

}

実行結果
Exception Result MaltiCatchTest$SampleAException

今回はargsパラメータに何も入力していなかったので、「SampleAException」 がthrowされました。

マルチキャッチの制約として継承関係の例外をキャッチできないことです。

以下はコンパイルエラーになります。

public class MaltiCatchTest2 {

public static void main(String[] args) {
String param = args.length > 0 ? args[0] : "a";
try {
new MaltiCatchTest2().testException(param);
System.out.println("end");
} catch (SampleDException | SampleCException e) {
// SampleDException例外とSampleCException例外は継承関係にあるためコンパイルエラー
System.out.println("Exception Result " + e);
}
}

public void testException(String param) throws  SampleCException,SampleDException{
switch (param) {
case "a":
throw new SampleCException();
case "b":
throw new SampleDException();
default :
break;
}
}
class SampleCException extends Exception {

}

class SampleDException extends SampleCException {

}
}

感想として、例外がまとめてかけるようになったのでコードがすっきりしましたね。


人気ブログランキングへ

2016年9月11日日曜日

switch文での文字列使用

みなさん こんばんは。

今日は第1章の 「小さな言語使用の変更 Project Coin」 の途中まで読みました。

冒頭で何故プロジェクト名がCoinなのか?と言う名前の由来が書かれていて

そういうことなのか、と思いました。

そもそもProject Coin で何が変更になったのでしょうか。

・switch文での文字列が使用出来るようになった。

今まではif else 文で条件分岐していたところをswitch文で記述出来ることによりスマートに書ける

ようになった。気をつけたいところは文字列にNullが渡された時にNullPointerExceptionの例外が発

生するので事前にNullチェックが必要であること。

こんな感じで。。

if ( str == null ) {
// ・・・Nullの場合の処理
} else switch(str) {
case "test" :
// Null以外の場合の処理
break;
}

・2進数リテラルが使えるようになりました。

今までは10進数、8進数、16進数の3種類でしたが、2進数を使えることで計算の幅が広がりましたね。
10進数の「3」を2進数で表記すると = 0b11 2進数の表記は先頭に0bが付きます。

・数値リテラルで区切り文字(アンダースコア)が使えるようになりました。

今までは桁数が多くなると可読性が悪くなってました。

こんな感じ。。

int i = 1000000000;

この数値をパッと見でいくらなのかを把握するのは難しかったのですが、

int i = 1_000_000_000;

こんな感じでアンダースコアを付けることにより可読性が向上しました。

今日はここまで読みました。

感想としてswitch文は簡単な、if else文の代替えとして使えそう。

複雑な条件分岐は従来通りのif文を使うことになるでしょう。

2進数の計算処理は頻繁に使うことは無いでしょうが、今後使うケースがあるでしょう。

数値リテラルの区切り文字は個人的にはあまり可読性が良くなったかと言われると??

な感じです。


人気ブログランキングへ

現場で使える最新Java SE 7/8 速攻入門の読書日記①

みなさん。 こんばんは。

デザインパターンの生成に関するパターンが一段落したので、

今回は趣向を変えて読書日記を始めたいと思います。

自分は今までjavaの書籍をインプットばかりしてきたので、アウトプットも兼ねて重要な点を紹介し

ていけたらと思ってます。
今回この書籍を選んだのは、最新のJava言語の説明がとても分かりやすく

個人的に気に入ったことと、職場ではまだJavaSE6を使っているので

最新のJava言語を習得したいという意向がありました。

今回は「現場で使える最新Java SE 7/8 速攻入門」を読んでいきます。

以下 現場で使える最新Java SE 7/8 速攻入門の章構成
(目次)
はじめに
  • Chapter 1 小さな言語仕様の変更 ――Project Coin
  • 1.1 小さな言語仕様の変更
  • 1.2 switch文での文字列の使用
  • 1.3 2進数リテラル
  • 1.4 数値リテラルの区切り文字
  • 1.5 マルチキャッチ
  • 1.6 適切な型による例外の再スロー
  • 1.7 ジェネリクス型パラメータの省略
    • 1.7.1 ダイヤモンド演算子が使用可能な箇所
    • 1.7.2 ダイヤモンド演算子が使用できない箇所
  • 1.8 リソースの自動クローズ
    • 1.8.1 複数リソースの自動クローズ
  • 1.9 安全な可変長引数メソッド
  • 1.10 まとめ

Chapter 2 新しいファイルシステムインタフェース ――NIO.2

  • 2.1 新しいファイルシステムインタフェース
  • 2.2 ファイルシステムとパス
    • 2.2.1 Pathオブジェクトの生成
    • 2.2.2 Pathの機能
    • 2.2.3 PathとFileの相互変換
  • 2.3 Pathに対する操作
    • 2.3.1 コピー
    • 2.3.2 移動/名前の変更
    • 2.3.3 削除
    • 2.3.4 ファイル/ディレクトリの作成
    • 2.3.5 リンク
    • 2.3.6 ファイルの入出力
  • 2.4 アトリビュート
    • 2.4.1 Filesクラスのアトリビュート関連メソッド
    • 2.4.2 名前を指定したアトリビュートの取得/設定
    • 2.4.3 複数のアトリビュートの取得/設定
  • 2.5 ファイルツリーの走査
    • 2.5.1 ディレクトリのコピー
  • 2.6 ディレクトリの監視
  • 2.7 まとめ

Chapter 3 ラムダ式による新しいプログラミングスタイル

  • 3.1 ラムダ式と新しいプログラミングスタイル
  • 3.2 関数型インタフェース
    • 3.2.1 関数型インタフェースとは?
    • 3.2.2 汎用の関数型インタフェース
    • 3.2.3 関数型インタフェースの作成
  • 3.3 ラムダ式
    • 3.3.1 引数の型,丸カッコの省略
    • 3.3.2 波カッコとreturn文の省略
    • 3.3.3 実質的final
    • 3.3.4 ラムダ式の注意点
  • 3.4 デフォルトメソッド
    • 3.4.1 デフォルトメソッドの使用
    • 3.4.2 デフォルトメソッドと多重継承
  • 3.5 インタフェースのstaticメソッド
  • 3.6 メソッド参照
    • 3.6.1 クラスメソッド参照
    • 3.6.2 インスタンスメソッド参照
    • 3.6.3 コンストラクタ参照
  • 3.7 ラムダ式の使い道
    • 3.7.1 高階関数
    • 3.7.2 関数合成
  • 3.8 まとめ

Chapter 4 Stream APIによる内部イテレータ

  • 4.1 内部イテレーションとStream API
  • 4.2 内部イテレータ
  • 4.3 Stream API
    • 4.3.1 ストリームの処理手順
    • 4.3.2 ストリームの種類
  • 4.4 ストリームの生成
    • 4.4.1 コレクション,配列からの生成
    • 4.4.2 I/Oからのストリーム生成
    • 4.4.3 ストリームのファクトリメソッド
    • 4.4.4 その他のストリーム生成
  • 4.5 ストリームの中間操作
    • 4.5.1 プリミティブ型に対応したストリームに固有の中間操作
  • 4.6 ストリームの終端操作
  • 4.7 nullチェックとOptionalクラス
    • 4.7.1 生成
    • 4.7.2 値の取得
    • 4.7.3 その他のメソッド
    • 4.7.4 Optionalクラスの用途
  • 4.8 Stream APIを使用した従来のコードの書き換え例
    • 4.8.1 条件に合致する要素を取り出す
    • 4.8.2 要素から他の情報を抽出
    • 4.8.3 要素から他の情報を抽出し,平坦化
    • 4.8.4 要素のグルーピング
    • 4.8.5 要素を平坦化し,集計
    • 4.8.6 顧客ごとの購買履歴の統計をとる
  • 4.9 パラレルストリーム
    • 4.9.1 パラレルストリームの取得
    • 4.9.2 処理順序に依存する記述
    • 4.9.3 パラレルストリームに特有のメソッド
    • 4.9.4 Fork/Join Framework
    • 4.9.5 パラレルストリームの動作
    • 4.9.6 パラレルストリームの注意点
  • 4.10 まとめ

Chapter 5 ISO 8601とDate and Time API

  • 5.1 新しい日時のためのAPI
  • 5.2 ISO 8601
    • 5.2.1 協定世界時?UTC
    • 5.2.2 UTCと地方時の時差
    • 5.2.3 暦
    • 5.2.4 日時表記
    • 5.2.5 日付の表記
    • 5.2.6 時刻の表記
    • 5.2.7 日付と時刻の表記
    • 5.2.8 時間長と時間間隔の表記
    • 5.2.9 JIS X 0301による拡張
  • 5.3 Date and Time API
    • 5.3.1 日時クラスの概要
    • 5.3.2 LocalDateTimeクラス
    • 5.3.3 時差とタイムゾーン
    • 5.3.4 OffsetDateTimeクラス
    • 5.3.5 ZonedDateTimeクラス
    • 5.3.6 日時クラスの変換
    • 5.3.7 Dateクラス,Calendarクラスとの変換
    • 5.3.8 日時フォーマット
    • 5.3.9 時間間隔
    • 5.3.10 暦
  • 5.4 まとめ
  • おわりに

章構成を見た感じだと新しいファイルシステムやDate Time APIなど、どんなことが変わったのか気になりますね。

次からは章ごとに読んだ感想や前のJavaバージョンとどの点が良くなったか等の視点で書いていきたいです。

人気ブログランキングへ

2016年9月10日土曜日

prototypeパターン

今日はprototypeパターンを見ていきましょう。

prototypeパターンとはざっくり言うと、原型となるオブジェクトを複製して新たなオブジェクトを生成

するパターンと言えるでしょうか。

Javaオブジェクトは、メソッドClone()を使って複製することができます。

Jobj j1 = (Jobj)j0.clone();

メソッドclone()は、常にObject型を返しますのでクローン生成しようとしているオブジェクトの実際の

型にキャストしなければなりません。このメソッドには下記の制約があります。

・ protetedなメソッドであり、同じクラスあるいはサブクラスからのみ呼び出せる。
・インターフェースCloneableをimplementsすると宣言されたオブジェクトだけがクローン生成できる。

クラスObjectのメソッドclone()はprotectedですから、具象クラス中にpublicなクローンメソッドを作り

そこからprotectedなclone()にアクセスします。

簡単な例を見てみましょう。

// prototype
public class SoccerSenshu implements Cloneable {

private String name;

public SoccerSenshu(String name) {
this.name = name;
}

public Object cloneMe() throws CloneNotSupportedException {
return super.clone();
}

public String toString() {
return "選手名は " + name;
}
}

// クライアントクラス
public class Client_Cloneable {

public static void main(String args[]) throws CloneNotSupportedException {
SoccerSenshu senshu1 = new SoccerSenshu("マラドナ");
SoccerSenshu senshu2 = (SoccerSenshu) senshu1.cloneMe(); // クローン
System.out.println(senshu1);
System.out.println(senshu2);
}
}

実行結果
選手名は マラドナ
選手名は マラドナ

同じオブジェクトがコピーされましたね。

しかしそもそも何故複製が必要なのでしょうか?

例としてある答えを得るのに、大規模なデータベースに数多くの問い合わせが必要となる場合、

その答えがテーブルあるいはResultSetとして一旦得られれば、それを操作することによって

(他に問い合わせを発行することなく)別の答えも導き出せるでしょう。

このように負荷の大きい作業を軽減する目的で使われることが多いです。

人気ブログランキングへ


2016年9月8日木曜日

Builderパターン

みなさん こんばんは。

今日はBuilderパターンを見ていきましょう。

Builderパターンとはその名の通り建築物を作るかのようにオブジェクトを作るパターンと言いま

しょうか。

言葉で説明するより、さっそくどんな感じなのか見ていきましょう。
以下、Builderパターンのクラス図

// 車クラス クラス図Productに該当
public class Car {

private String engin;

private String taiya;

private String name;

public String getEngin() {
return engin;
}

public void setEngin(String engin) {
this.engin = engin;
}

public String getTaiya() {
return taiya;
}

public void setTaiya(String taiya) {
this.taiya = taiya;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String toString(){
return "「 チーム名 "+getName()+" : エンジン "+getEngin()+" : タイヤ "+getTaiya()+" 」";
}
}

// ビルダー クラス図Builderに該当
public interface Builder {

void buildEngin();

void buildTaiya();

void buildName();

Car getResult();
}

//ビルダー実装クラス1 クラス図ConcreateBuilderに該当
public class McLarenBulder implements Builder {

private Car car;

public McLarenBulder(){
this.car = new Car();
}

@Override
public void buildEngin() {
this.car.setEngin("ホンダ");
}

@Override
public void buildTaiya() {
this.car.setTaiya("ブリジストン");
}

@Override
public void buildName() {
this.car.setName("マクラーレン");
}

@Override
public Car getResult() {
return this.car;
}
}

// ビルダー実装クラス2 クラス図ConcreateBuilderに該当
public class FerrariBuilder implements Builder {

private Car car;

public FerrariBuilder(){
this.car = new Car();
}
@Override
public void buildEngin() {
this.car.setEngin("フェラーリ");
}

@Override
public void buildTaiya() {
this.car.setTaiya("ピレリ");
}

@Override
public void buildName() {
this.car.setName("フェラーリ");
}

@Override
public Car getResult() {
return this.car;
}
}

// ディレクター クラス図Directorに該当
public class Director {

private Builder builder; // Has-a関係

public Director(Builder builder){
this.builder = builder;
}

public Car constructFoumura1(){
this.builder.buildEngin();
this.builder.buildTaiya();
this.builder.buildName();
return this.builder.getResult();
}
}

// クライアントクラス
public class Client_BuilderTest {

public static void main(String[] args) {
Director d1 = new Director(new McLarenBulder());
Director d2 = new Director(new FerrariBuilder());
Car mcLaren = d1.constructFoumura1();
Car ferrari = d2.constructFoumura1();
System.out.println(mcLaren);
System.out.println(ferrari);
}
}

実行結果
「 チーム名 マクラーレン : エンジン ホンダ : タイヤ ブリジストン 」
「 チーム名 フェラーリ : エンジン フェラーリ : タイヤ ピレリ 」

クライアントクラスでマクラーレンとフェラーリBuilderをDirectorに渡して、

DirectorがconcreateFoumura1()メソッドを呼び出すと、エンジンとタイヤの付いたF1カーが

返却されます。本例は簡単な例でしたが、本来はもっと複雑な複合構造のオブジェクト生成物が返

却されるでしょう。




人気ブログランキングへ

2016年9月7日水曜日

Singletonパターン

今回はSingletonパターンを紹介しますね。

Singletonパターンはクラスのインスタンスをアプリケーション内で一つだけ生成するパターンです。

クラスのインスタンスを一つだけに制限したい例はいくらかあるでしょう。

例えば、ファイルアクセス、ロギング処理、キャッシュ、コネクションプールなどでしょうか。

実際これらのオブジェクトを2つ以上インスタンス化したら、

プログラムの誤動作やつじつまの合わない結果といったあらゆる問題が起きてしまいます。

ではどんな感じで実装するのか見てみましょう。

// シングルトン
public class Singleton {
private static Singleton instance = new Singleton(); // static初期化でインスタンス生成
private Singleton() { }; // コンストラクタはprivateであること
public static Singleton getInstance() { // インスタンスの取得はこのstaticメソッドで取得
return instance;
}
public void print(String s) {
System.out.println(s);
}
}

// メインクラス
public class Client {
public Client() {
Singleton s1 = Singleton.getInstance();  // 1回目
s1.print("こんにちは。シングルトン1");
Singleton s2 = Singleton.getInstance();  // 2回目
s2.print("こんばんは。シングルトン2");
if (s1 == s2 ) {
System.out.println("同じインスタンス");
}
System.out.println("シングルトン1" + s1);
System.out.println("シングルトン2" + s2);
}

public static void main(String[] args) {
new Client();
}
}

ここではシングルトンインスタンスを2回要求した後で、
同一のインスタンスかどうかを s1 == s2 によってチェックしています。
このプログラム実行結果は下記になりました。

・実行結果
こんにちは。シングルトン1
こんばんは。シングルトン2
同じインスタンス
シングルトン1jp.co.kouji.umeda.core.Singleton@2e4f7bc2
シングルトン2jp.co.kouji.umeda.core.Singleton@2e4f7bc2

Singleton.getInstance();を二回呼び出してますが、

実行結果はシングルトン1とシングルトン2が同じインスタンスになってますね。

ここでは簡易的な例にしましたが通常は上記で記載されている通り、

ロギングやキャッシュなどのアクセスオブジェクトとして使われたりします。


人気ブログランキングへ