Upload
appresso-engineering-team
View
481
Download
0
Embed Size (px)
Citation preview
nio2(JSR203)勉強会
大崎 瑶
nio2
• nio(JSR51)の積み残し
• 非同期I/O
• マルチキャストサポート
• ファイルシステムインタフェース
ファイルシステムインタフェース
java.nio.file.FileSystem
FileSystem fileSystem = FileSystems.getDefault();
Path path = fileSystem.getPath(“foo.txt”);
FileSystemの取得
Pathの取得
List<FileSystemProvider> providers =
FileSystemProvider.installedProviders();
FileSystemはFileSystemProviderによって提供される。一覧は、installedProviders()で取得できます。
ディレクトリ
DirectoryStream<Path> directory =Files.newDirectoryStream(path);
for (Path childPath: directory) {...
}
if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) {...
}
ディレクトリの情報はDirectoryStreamで取得できます。DirectoryStreamはIterableをのサブインタフェース
Pathがディレクトリかどうかを調べるにはFilesユーティリティを使います。
入出力
Path path = ...;InputStream iStream = Files.newInputStream(path);OutputStream oStream1 = Files.newOutputStream(path);OutputStream oStream2 =
Files.newOutputStream(path, StandardOpenOption.APPEND);
StandardOpenOption.CREATTEStandardOpenOption.CREATE_NEWStandardOpenOption.READStandardOpenOption.WRITEStandardOpenOption.APPEND
入出力
Path path = ...;BufferedReader reader =
Files.newBufferedReader(path, Charset.defaultCharset());
BufferedWriter writer1 =Files.newBufferedWriter(path, Charset.defaultCharset());
BufferedWriter writer2 =Files.newBufferedWriter(path, Charset.defaultCharset(),
StandardOpenOption.APPEND);
FileChannel や SeekableByteChannel といったファイルチャネルを取得することもできます。
ファイル・ディレクトリの作成
Path path = fileSystem.getPath(“filename”);Files.createFile(path);
path = fileSystem.getPath(“dirname”);Files.createDirectory(path);
path = fileSystem.getPath(“parentdir/childdir”);Files.createDirectory(path);
ファイル・ディレクトリのコピー
Path foo = fileSystem.getPath("foo.txt");Path bar = fileSystem.getPath("bar.txt");Path baz = fileSystem.getPath("baz.txt");
// ファイルのコピーFiles.copy(foo, bar);
// ファイルのコピー(上書きコピー)Files.copy(foo, bar, StandardCopyOption.REPLACE_EXISTING);
// ファイルのコピー(属性を含む)Files.copy(foo, baz, StandardCopyOption.COPY_ATTRIBUTES);
StandardCopyOption.REPLACE_EXISTINGStandardCopyOption.COPY_ATTRIBUTESStandardCopyOption.ATOMIC_MOVE
メタデータ
• Filesクラスのユーティリティメソッド
– ex. Files.setOwner(),Files.getLastModifiedTime()
• Files.getAttribute(),Files.setAttribute()
• FileAttributeViewインタフェース
Filesクラスのユーティリティメソッドを使ったメタデータの取得設定
FileTime lastModified = File.getFileLastModifiedTime(path);UserPricipal owner = File.getOwner(path);Set<PosixFilePermission> permission =
File.getPosixFilePermission(path);
File.setFileLastModifiedTime(path, lastModified);File.setOwner(path, owner);File.setPosixFilePermission(path, permission);
UserPrincipalLookupService service = FileSystems.getDefault().getUserPrincipalLookupService();
UserPrincipal user = service.lookupPrincipalByName("ap091011");
UserPrincipalはUserPrincipalLookupServiceから取得することが出来る。
Files.getAttribute()Files.setAttribute()
FileTime lastModified = (FileTime) File.getAttribute(path, “lastModifiedTime”);
FileTime creationTime = (FileTime) File.getAttribute(path, “creationTime”);
UserPrincipal owner = File.getAttribute(path, “acl:onwer”);
File.setAttribute(path, “lastModifiedTime“, lastModified);File.setAttribute(path, “creationTime”, creationTime);File.setAttribute(path, “acl:owner”, owner);
ファイル・ディレクトリの移動・削除
// ファイルの移動Files.move(foo, bar);// ディレクトリの移動Files.move(dirFoo, dirBar);
// ファイルの削除Files.delete(bar);
// ファイルが存在していなくても、例外をスローしないFiles.deleteIfExists(foo2);
ファイルの移動とディレクトの移動は同じメソッド。同じディレクトリ内のファイル(ディレクトリ)の移動はリネーム
ファイルの移動とディレクトの移動は同じメソッド。ディレクトリの場合ディレクトリ内にファイルがあると例外がスローされる
FileAttributeViewインタフェース
BasicFileAttributeView attrView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
FileTime lastModified = attrView .readAttributes().lastModifiedTime();FileTime creationTime = attrView .readAttributes().creationTime();
attrView.setTimes(lastModified, lastAccess, creationTime);
AclFileAttributeView acl =Files.getFileAttributeView(path, AclFileAttributeView.class);
UserPrincipal owner = acl.getOwner();
java.nio.file.FileVisitor
• preVisitDirectory()
–ディレクトリに入る時
• postVisitDirectory()
– ディレクトリから出る時
• visitFile()
– ファイルの訪問時
• visitFileFailed()
– ファイルの訪問に失敗した時
java.nio.file.WatchServicePath dest = fileSystem.getPath("dest");
WatchService watcher = fileSystem.newWatchService();
dest.register(watcher,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
Pathに対してWatchServiceを登録します。
java.nio.file.WatchServicewhile (true) {
WatchKey key = null;
try {
key = watcher.take();
} catch (InterruptedException ex) {
break;
}
}
ざんねんながら、自分でポーリングしなくてはなりません。ただし、同期化してくれるので便利といえば、便利です。書き込み途中で何かしようとしちゃう問題とか・・・
非同期I/O
• AsynchronousSocketChannel
• AsynchronousServerSocketChannel
• AsynchronousFileChannel
• AsynchronousDatagramChannel
SocketChannel, ServerSocketChannel, FileChannel, DatagramChannelの非同期版
それぞれのサブクラスにはなっていません
非同期I/O
• Future<V>インタフェースを使う方法
• java.nio.channels.CompletionHandlerを使う方法
非同期を実現するのに2つの方法がある。
AsynchronousSocketChannel
AsynchronousSocketChannel client =
AsynchronousSocketChannel.open();
client.connect(server.getLocalAddress()).get();
Future<AsynchronousSocketChannel> acceptFuture = server.accept();
AsynchronousSocketChannel ch = acceptFuture.get();
クライアントソケットの作成
サーバー側でアクセプトしたソケット
AsynchronousServerSocketChannel(Future)
Future<AsynchronousSocketChannel> acceptFuture = server.accept();
接続を受け付けるまでブロックされます
AsynchronousSocketChannel worker = future.get();
acept()はブロックされません。
AsynchronousServerSocketChannel(CompletionHandler)
acept()はブロックされません。
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
public void completed(AsynchronousSocketChannel ch, Void att) {
...
}
public void failed(Throwable exc, Void att) {
...
}
)}
AsynchronousFileChannel
AsynchronousFileChannel fileChannel =
AsynchronousFileChannel.open(Paths.get("myfile"));
Future<Integer> readFuture = fileChannel.read(dst, pos);
ByteBuffer buffer = ByteBuffer.allocate(1024);
int pos = 0;
while (true) {
buffer.clear();
Future<Integer> future = channel.read(buffer, pos);
int len = future.get();
if (len < 0) {
break;
}
pos += len;
}