28 Feb 2015, 11:12

Coursera で Reproducible Research をうけた

はじめに

以前, org-mode と R を組み合わせたらとても気持ちがよかった.

そこで, もうすこし R と org-mode の可能性を知りたくて, Coursera で Reproducible Research をうけた.

内容

全部で 4 週間. 動画リストが以下にある.

初めの週で, Reproducible Research についての概要について語られる.

Reproducible Research という考え方の情報が少ないので, ネットで情報を検索するよりも, 講義資料が一番役に立つ.

2,3 週目では, 実際に Reproducible Research を実践するためのツール が紹介される. この講義では, knitr をつかう.

紹介された内容にしたがって, 課題が 2 つ出される. github, rpubs に課題を投稿してペアレビューをする.

以下, 自分の提出した課題.

最後の週は, Reproducible Research の実施例が紹介される. 動画は Youtube でも見れる.

感想

Emacs で頑張る

講義では RStudio を利用することが求められるのだが, もともとの動機が Emacs org-mode で Reproducible Research をしたかったので, RStudio を頑なに拒否して, Emacs をつかった.

文芸的プログラミングと R はとても相性がいい

文芸的プログラミングと R はとても相性がいい. この件について再認識した.

そしてなにより, 生成されるドキュメントがとてもかっこいいところが 一番気に入った. こういう感動を忘れずにいたい.

Reproducible blog を目指して

再現可能性という考え方もおもしろいと思った.

Reproducible Research が注目を集める背景には, 以下のようなことがある.

自分は研究者ではないので, いまいちピンとこないのだけれども, 身近な問題に置き換えると, ネット上でみつけたコード辺を動かしてみよう としても動かないことがままある.

もしかしたら, 動かないコードやコンパイルできないコードを, 何食わぬ顔で自分も公開しているかもしれない.

最近では, Web 上でコードを実行できるサービスも出てきた.

このようなサービスを利用することで,

Reproducible Blog 再現可能なブログ

を目指そうと思った.

学習メモ

以下, 自分の勉強メモを

Reproducible Research とは

再現可能な研究. 再現可能なデータ分析.

The ultimate product of academic research is the paper along with the full computational environment used to produce the results in the paper such as the code, data, etc.

Computational X の X の部分にすべて適用できる考え方

  • コンピュータ心理学
  • コンピュータ生理学
  • コンピュータ生物学 … etc.

クラシックの交響曲は様々な楽器かそれぞれのメロディーを奏でて, 一つの音楽をつくる.

テンポや曲調がまったく同じ音楽を再現することは不可能だ. (Replication:複製は不可能)

しかし, 楽譜にしたがって演奏することで, 演奏者が違っても, 世界中のどこでも, 作曲家の示した音楽を再現させることは可能だ. (Reproducible: 再現)

音楽における楽譜がデータ解析におけるスクリプトとなる.

以下のメリットがある.

  • Transparency
  • Data Availability
  • Software / Methods Availability
  • Improved Transfer of Knowledge

統計解析は異常値の除去の方法によって, 得られる結果が異なることがある. 得られた結果の論拠を強くするために, 論拠となったデータを誰もが分析で きるかたちで共有することが重要となる.また, だれもがデータを分析でき ることで, より議論をタイムリーに生み出しやすくできる.

登場の背景

技術の向上が, Reproducible Research の台頭を支えている.

  • コンピュータの計算能力が極めて向上し, 洗練された解析が可能になった.
  • 既存のデータベースが “megadatabeses”にマージ可能となった.
  • データ収集のスループットが新しい技術によって向上した.

Literate (Statistical) Programming

記事は text , code (chunks) からなる

  • A documantation Language (human redable)
  • P programming language (machine readable)

文芸プログラムは

  • 人間が読みやすいドキュメントに waved される.
  • コンピュータが実行可能なドキュメントに tangled される.

Research Pipeline

  1. Mesured Data
    • Processing code
  2. Analytic Data
    • Analytics code
  3. Computational Resuluts -> Presentation code
  4. Presentation Results
    1. Fugures
    2. Tables
    3. Numerical Summaries
  5. Articles

管理するファイルの分類

  • Data
    • Raw data: 生データ
    • Processed data: 前処理がおわったデータ
  • Figures
    • Exploratory figures 分析の途中でできる図.
    • Final Figures: 最終結果の図.
  • R Code
    • Raw scripts
    • Final scripts
  • Text
    • README.md
    • R markdown

R markdown

R Studio のための マークアップ言語.

RStudio と R markdown を利用することで 簡単に Reproducible な report が作成可能.

knitr

HTML や markdown, pdf への export. R と Markdown を利用して文芸的プログラミングをするためのツール.

CRAN から取得可能.

install.packages ('knitr', dependencies = TRUE)

evidence-based data analysis

26 Feb 2015, 14:54

Emacs Lisp で SICP に挑戦するさいの落とし穴

はじめに

SICP を Emacs Lisp でとくという, やや無謀なことに挑戦中.

SICP 自体は Scheme をベースにかかれているので, 例題や回答を elisp に置き換えながら読んでいく.

Emacs Lisp は不自由なもので, 結構ハマリポイントがあった.

第一章がようやく終わったところで, いったんたまったノウハウをはきだしておこう.

よくある置き換え

defun

毎回ある置き換え.

;; scheme
(define (hoge x) x)

;; emacs lisp
(defun hoge (x) x)

cond

cond の書き方について,

  • scheme は 一番最後に else をつける.
  • elips は 一番最後に t をつける.
(cond ((= 1 1) 1)
      (else 2))

(cond ((= 1 1) 1)
      (t 2))

高階関数

関数にの頭に ‘をつけて別の関数の引数にすると, 関数は評価されずに引数に渡すことができる.

評価するときは, (funcall f) のように funcall を呼ぶ.

ローカル変数

elips は scheme のように, 関数の中に関数をかいても 変数や関数のスコープを限定できない.

let, let*, letrec が利用をうまくつかって, ローカルな変数や関数をつかう.

ローカル関数の定義

let + lambda を利用する, 変数に無名関数を bind させることで実現する.

(let ((p (lambda (a) (message a))))
    (funcall p "hoge"))

letrec を利用する方が正式か?

letrec の rec は 再帰のこと. let は再帰関数が定義できないが, letrec はできる.

落とし穴

Dynamic Scope

Emacs Lisp は Dynamic Scope という方式をとり, 名前空間がない. なので, 安直な a とか sum とかいう関数を名づけてしまうと, うっかり他の関数と競合する.

できるだけ, 他とかぶらない関数名をつけるほうが無難.

Emacs24 からは, ファイルの先頭に以下を書くと, setq で宣言した変数は本当の Lexical Scope になる.

-*- lexical-binding: t -*- 

高階関数で 関数がわたせない

無名関数を入力しても, なぜか Symbol value as void となる.

以下を行頭に買いて, M-x eval-buffer で評価することで, 回避できた.

;; -*- lexical-binding: t -*- 

max-lisp-eval-depth 発生

Emacs Lisp は 末尾最適化がされないため, 深い再帰処理をかくと, よくクラッシュする.

これによって, 解くのを諦めた問題多数. これが Elisp の限界か.

その他

自分一人で行き詰まった時は, 先人の知恵を拝借する.

22 Feb 2015, 11:21

分散システムにおける異常検出とスゲぇ HeartBeat についてのまとめ

はじめに

Coursera でとっている Cloud Computing Concepts で Gossip-Style HeartBeat というものが出てきたので詳しく調べてみた.

以前の仕事について

一年以上前の話になるのだが, 以前のプロジェクトの仕事について書く.

以前は, ストレージ の 異常検出機能を作っていた.

信頼性を確保するために, 部品は冗長化されている. 最大で, 8 ノードの部品が互いを監視しあうような構成.

あるの部品が故障した場合に, 別の部品で異常を検出して, その部品を部分的に停止するような機能.

監視のロジックは単純で, 定期的に相手と通信して, 通信タイムアウトが多発したら異常と判断する.

異常検出はそれがすべてと思っていた. しかし, 実際はずっと奥が深かったのだった.

ということ. 以下, 詳しく.

Failure Detector

分散システムのノードの中で, 異常検出を担うものを Failure Detector という.

In distributed computing, a failure detector is an application or a subsystem that is responsible for detection of node failures or crashes in a distributed system.

以下の論文で提出された概念.

Failure Detector の解説を噛み砕いて書いてある.

Failure Detector の異常検出方法

2 種類のパターンしかない.

Alive - Suspected - Failed という 3 つの状態遷移がある.

故障したかを確認するのに, タイムアウトの仕組みを使うことが多い

Ack-Ping Protocol

能動的にプロセスがお互いに”生きてますか”という旨のメッセージを送信しあう.

  • A は B に T 秒ごとに ping を投げる.
  • B は A に ack を応答する.
  • A は B からの応答が 2T 秒 以内が帰ってこなければ B を異常と判断. タイムアウトは 2T 以内.

Heartbeating Protocol

受動的に相手からの通信をまつ.

  • B -> A へ T 秒ごとに heartbeat を投げる.
  • A は T 秒ごとに heartbeat を受信する.
  • A は B からの heartbeat が 3T 秒間なければ, A は B を異常と判断.

Faulure Detector の特徴

Property Description


Completeness each failure is detected. Accuracy there is no mistaken detection. Speed Time to first detction of a failure. Scale Equal Load on each member/ Network Message Load. (No bottlenecks, single failure point)

HeartBeating

ネットワーク上で, コンピュータやネットワーク機器が自身が 正常に稼動していることを外部に知らせるために送る信号.

Keep-Alive ともいう.

HeartBeating の種類

実施方法は, いろいろある.

Centralized Heartbeating

ひとつのノードが他のすべてにハートビートを送る.

scale において x (single point of failure)

Ring Heartbeating

円上にならんだ, ノードがとなりのノードにハートビートを送る.

Accuracy において x.(いつも検出できない)

All-to-all Heartbeating

それぞれのノードがそれぞれのノードに対してハートビートを送る.

通信の負荷が高い.

Gossip-style Heartbeating

Better All-to-all Heartbeating.Probabilistic Failure Detector.

Multicast 通信で, 特定のグループに情報を伝達するためのよい手段.

  • epidemics とも呼ばれている.
  • 速く, 信頼性があり, スケーラブル.

すべてのノードに heartbeat をするのではなく, ランダムに選出したノードに対して heartbeat を実施する.

Load (負荷) は N に比例しないという特徴がある. つまり, いくらでもノードを動的に拡張できるということ.

Gossip はうわさのこと. 人のうわさがあっという間に広まるのには理論的根拠があった.

あるノードが通信を受信すると, ランダムに選んだ n つのノードにメッセージを送信する.

ウワサや伝染病が広まるように, 情報が伝達していく.

Amazon EC2/S3 で利用されている.

Membership protocols

Gossip-style を実現するための方法.

メンバシップリストというデータを互いのノードが送信しあって, 同期をする方式.

  • ノードを追加するときは, メンバシップリストにノードを登録する.
  • ノードを削除するときは, メンバシップリストからノードを削除する.

メンバシップリストは, Gossip-Style Multicast によって, あっという間に各ノードで共有される.

Snippet

たとえば, 30%の確率で まわりのノードに HeartBeat をおくっていても, ちゃんと異常を検出できる.

すべてのノードに送らなくてもいいことに驚いた.

void MP1Node::sendHeartBeat () {
  Address address;
  double prob = 0.3;

  for (MemberListEntry entry: memberNode->memberList) {

    // 自分自身はスキップ
    if (isSameAddress (getAddress (entry), memberNode->addr)) {
      continue;
    }

    // ランダムに送信する (Gossip)
    if ((((double) (rand () % 100))/100) < prob) {
      address = getAddress (entry);
      sendMessage (HEARTBEAT, &address);
    }
  }
}

Fault-tolerant Patterns

Fault-tolerant Patterns の分野は Pattern 化されている.この分野の話をもっと知りたい.

Fault-tolerant で利用される概念がコンパクトにまとまっている.

Fault-tolerant のパターン. POSA と同じ出版社.

上の本の書評

Pattern についてまとまった PDF.

おわりに

異常検出は奥が深かった!

今回, 調べてみて驚いたのは, こういう異常検出というのは,

  • Fault-Tolerant という用語で検索するとたくさん情報がでてくる
  • 異常検出方法は, 体系的にまとまっている
  • スケーラブルなハートビートが存在する

ということ. 自分の視野の狭さと, 分散システムのおもしろさを感じた.

特許を考えるにはあまりに無知だった

今まで, 自分の頭でいろいろな分散ノードの異常検出方法について, 特許になりそうなものを考えてきた.

しかし, この分散システムにおける異常検出というのは, すでにいろいろなアイデアが出されていることを知った.

分散シテステムの鉄板本にいろいろなアイデアが載っている.

それらを知らずに自分でアイデアをひねり出すことは,遠回りのような気がした. また, そういうアイデアがすでにたくさんあることにも驚きだった.

まずは先人のアイデアを身につけることを優先したほうがよい気がした. そして, それらのアイデアを知った上で, プラスアルファで新しいアイデアが生まれるかもしれないと思った.

分散システムにおける論文について調べるとおもしろいかもしれない.

17 Feb 2015, 13:50

フリーで高性能な OSS アンケートツール!LimeSurvey を Windows で動かす

はじめに

職場で簡単なアンケートを実施したいとおもった.

メールベースで作成すると集計が大変だ. できれば CSV 形式で出力して, 相関関係を Excel か R で分析までしたいところ.

なにかうまい手はないかと思っていたら, OSS のアンケートツールを見つけたので試す.

環境

  • Windows 8.1

職場でも, あいている Windows サーバが自分の端末にいれようと考えている.

ちなみに, LimeSurvey の HP には, サポートは 7 までとかいてあるが, 8 でもばっちり動いた.

LimeSurvey について

フリーで高性能な OSS アンケートツール.

ネットで調べてると, ほぼこのツール以外に見つからない. デファクトスタンダードっぽい.

Windows にインストール

インストールは, 以下の方法がある.

  • appatch & mysql がある環境にインストール.
  • (windows) xampp 上で動作させる.

Windows でサクッとためするには, XAMPP がおすすめ.

以下からダウンロードして, インストーラを起動するだけという簡単さ!

ちなみに, インストール先でデフォルトの C:xampp 以外をしていすると, 動作しなかった. おそらく PHP の PATH 設定かと.

XAMPP をイントラネット内に公開

もともと, xampp は Windows ローカル環境で PHP などの開発環境を作成する ためのツール. 今は, vagrant とか docker が取って代わった気がする.

そのため, xampp のサイトを外部に公開するには, 一工夫必要.

サンプルでアンケート作成

以下, スクリーンショットとともに. まずは, admin/password でログイン.

file:c:/cygwin64/home/tsu-nera/futurismo/blog/img/SnapCrab_NoName_2015-2-17_22-8-41_No-00.png

ログインすると, アンケート作成のガイダンスが出る.

file:c:/cygwin64/home/tsu-nera/futurismo/blog/img/SnapCrab_NoName_2015-2-17_22-17-54_No-00.png

ガイダンスにしたがって作成した. 次に作成したアンケートをテスト.

file:c:/cygwin64/home/tsu-nera/futurismo/blog/img/SnapCrab_NoName_2015-2-17_22-23-45_No-00.png

完了!!

file:c:/cygwin64/home/tsu-nera/futurismo/blog/img/SnapCrab_NoName_2015-2-17_22-23-58_No-00.png

おわりに

Windows 環境での導入の気楽さに感動した.

作成はやや手間がかかるものの,

  • その後の集計作業
  • イケテル UI
  • 回答率の管理

などなど, かける労力に対するリターンは大きそうな印象を受けた.

もう少しいじってみて利用できそうか見極めてみる.

15 Feb 2015, 10:22

Flycheck で g++ の日本語表記のコンパイルエラーがパースできていなかった (C/C++)

はじめに

Emacs の エラーチェッカーで flycheck がある.静的文法チェック. flymake の後継.

C++ でつかってみると, どうも動かないので調べてみたメモ.

Build-in

マニュアルによると, gcc, clnag, cppcheck が default のチェッカーとして用意されている.

パーサーを見てみると..

ソースを除いてみると, たとえば gcc のパーサーは以下.

(flycheck-define-checker c/c++-gcc
  "A C/C++ syntax checker using GCC.

Requires GCC 4.8 or newer.  See URL `https://gcc.gnu.org/'."
  :command ("gcc"

    "長いので途中省略"

  :error-patterns
  ((error line-start
          (message "In file included from") " " (file-name) ":" line ":"
          column ":"
          line-end)
   (info line-start (file-name) ":" line ":" column
         ": note: " (message) line-end)
   (warning line-start (file-name) ":" line ":" column
            ": warning: " (message) line-end)
   (error line-start (file-name) ":" line ":" column
          ": " (or "fatal error" "error") ": " (message) line-end))
  :error-filter
  (lambda (errors)
    (flycheck-fold-include-levels (flycheck-sanitize-errors errors)
                                  "In file included from"))
  :modes (c-mode c++-mode)
  :next-checkers ((warning . c/c++-cppcheck)))

おかしいなぁと悩むこと 1 時間近く… パーサーの文字が英語だと気づいた…

自分の環境では, g++ を走らせると,

  • error -> エラー
  • Warining -> 警告

と表示される.

日本語表記で checker を定義

しかたがないので, 自分で定義をする.

(require 'flycheck)
(add-hook 'c-mode-common-hook 'flycheck-mode)

(defmacro flycheck-define-clike-checker (name command modes)
  `(flycheck-define-checker ,(intern (format "%s" name))
     ,(format "A %s checker using %s" name (car command))
     :command (,@command source-inplace)
     :error-patterns
     ((warning line-start (file-name) ":" line ":" column ": 警告:" (message) line-end)
      (error line-start (file-name) ":" line ":" column ": エラー:" (message) line-end))
     :modes ',modes))
(flycheck-define-clike-checker c-gcc-ja
                   ("gcc" "-fsyntax-only" "-Wall" "-Wextra")
                   c-mode)
(add-to-list 'flycheck-checkers 'c-gcc-ja)
(flycheck-define-clike-checker c++-g++-ja
                   ("g++" "-fsyntax-only" "-Wall" "-Wextra" "-std=c++11")
                   c++-mode)
(add-to-list 'flycheck-checkers 'c++-g++-ja)

基本的なところにかなりハマってた…

14 Feb 2015, 05:51

Emacs で現在のファイルのパスを取得してクリップボードに保存 (org-link も)

はじめに

Emacs で現在のパスを取得する方法を調べてみました.

以下の記事を参考にしました.

現在のファイルのパスを取得してクリップボードに保存

現在開いているファイルのパスを保存. dired を開いているときはディレクトリパスを保存.

  (defun my/get-curernt-path ()
    (if (equal major-mode 'dired-mode)
    default-directory
    (buffer-file-name)))

(defun my/copy-current-path ()                                                         
  (interactive)
  (let ((fPath (my/get-curernt-path)))
    (when fPath
      (message "stored path: %s" fPath)
      (kill-new (file-truename fPath)))))

(global-set-key (kbd "C-c 0") 'my/copy-current-path)

org-link 形式で クリップボードに保存

org-mode のヘビーユーザなので, url を org-link で扱いたい. org-link に変換した上で保存.

(defun my/copy-current-org-link-path ()
  (interactive)
  (let* ((fPath (my/get-curernt-path))
     (fName (file-relative-name fPath)))
    (my/copy-org-link fPath fName)))

(defun my/copy-org-link (my/current-path my/current-title)
  (let ((orgPath
     (format "[[%s][%s]]" my/current-path my/current-title)))
    (message "stored org-link: %s" orgPath)
    (kill-new orgPath)))

(global-set-key (kbd "C-x @ @") 'my/copy-current-org-link-path)

追記

よく考えたら, org-store-link という関数がすでにあったではないか!!

車輪の再発明をしてしまった.

eww で現在開いているページを org-link 形式で クリップボードに保存

eww-copy-page-url (w) で現在の URL をクリップボードにコピーできる.

(defun eww-copy-page-org-link ()
  (interactive)
  (my/copy-org-link (eww-current-url) (eww-current-title)))
(define-key eww-mode-map (kbd "0") 'eww-copy-page-org-link)

13 Feb 2015, 15:08

RPubs に Emacs から投稿してみた (R Markdown, org-mode)

はじめに

RPubs は R Studio に依存する R markdown 共有サービスなのですが, R Studio を利用せずに, Emacs から 投稿できるか調べてみました.

rpubsUpload をつかう

結論としては, rpubsUpload という関数を利用すると, コードを評価することで RPubs に投稿できる.

# Upload をする
result <- rpubsUpload ("My document title", "Document.html")

# Upload 結果をブラウザで開く
if (!is.null (result$continueUrl))
   browseURL (result$continueUrl)
else
   stop (result$error)

ブラウザを開くと, ログイン画面が現れるのでログインして OK を押せばよい.

Emacs から投稿

R markdown を Emacs から投稿

Emacs で R Markdown を作成して, 投稿することができる.

以下の記事を参考にして Rmd を html に変換して, コードを評価する.

# Upload Test

see: [rpubsUpload - R Graphical Manual] (http://rgm3.lab.nig.ac.jp/RGM/R_rdfile?f=markdown/man/rpubsUpload.Rd&d=R_CC)

# upload a document

this is my first upload from function

```{r sample, echo=TRUE, results='hide'}
require (markdown)
result <- rpubsUpload ("rpubsUpload usage", "RpubsUploadSample.html")
if (!is.null (result$continueUrl)) {
    browseURL (result$continueUrl)
}else {
    stop (result$error)
}
```

org-mode から投稿

markdown よりも org-mode のほうがなれているということもあり, org-mode からも投稿してみました.

M-x org-html-export-to-html で org-mode を html に変換して, コードを評価.

#   * Upload Test
#   this is my first upload from Emacs org-mode
#  
# ** convert to html
#    M-x org-html-export-to-html
#  
# ** run script
#  
# #+begin_src R :eval query
# require (markdown)
# result <- rpubsUpload ("Emacs org-mode upload", "UploadFromOrgMode.html")
# if (!is.null (result$continueUrl)) {
#     browseURL (result$continueUrl)
# }else {
#     stop (result$error)
# }
# #+end_src
#  

12 Feb 2015, 15:12

Emacs で knitr と R markdown を使う方法 (Rmd)

はじめに

coursera で, Reproducible Research の講座をとっています.

knitr の演習が出てきて, R Studio を使うように強いられます.

Emacs が捨てがたいので, knitr を Emacs で利用する方法について調べました.

knitr

knitr R と Markdown を利用して文芸的プログラミングをするためのツール.

CRAN から取得可能.

install.packages ('knitr', dependencies = TRUE)

polymode

polymode を利用すると, 複数のモードを共存させる. これを利用して R-mode (ESS) と markdown-mode を共存.

;; MARKDOWN
(require  'poly-markdown)
(add-to-list 'auto-mode-alist '("\\.md" . poly-markdown-mode))

;; R modes
(require  'poly-R)
(add-to-list 'auto-mode-alist '("\\.Snw" . poly-noweb+r-mode)
(add-to-list 'auto-mode-alist '("\\.Rnw" . poly-noweb+r-mode))
(add-to-list 'auto-mode-alist '("\\.Rmd" . poly-markdown+r-mode))

markdown への変換

ess-swv-knit で Rmd を md に変換できる.

HTLM への変換

html に変換するには, 以下の方法がある.

(defun rmarkdown-to-html ()
  (interactive)
  "Run knitr::knit2html on the current file"
  "https://gist.github.com/kohske/9128031"
  (shell-command
   (format "Rscript -e \"knitr::knit2html ('%s')\""
       (shell-quote-argument (buffer-file-name)))))

;; do this in R process
;; library (rmarkdown); render ("file_name.Rmd")

(defun ess-rmarkdown ()
  (interactive)
  "Compile R markdown (.Rmd). Should work for any output type."
  "http://roughtheory.com/posts/ess-rmarkdown.html"
  ; Check if attached R-session
  (condition-case nil
      (ess-get-process)
    (error 
     (ess-switch-process)))
  (let* ((rmd-buf (current-buffer)))
    (save-excursion
      (let* ((sprocess (ess-get-process ess-current-process-name))
         (sbuffer (process-buffer sprocess))
         (buf-coding (symbol-name buffer-file-coding-system))
         (R-cmd
          (format "library (rmarkdown); rmarkdown::render (\"%s\")"
              buffer-file-name)))
    (message "Running rmarkdown on %s" buffer-file-name)
    (ess-execute R-cmd 'buffer nil nil)
    (switch-to-buffer rmd-buf)
    (ess-show-buffer (buffer-name sbuffer) nil)))))

(define-key polymode-mode-map "\M-ns" 'ess-rmarkdown)

11 Feb 2015, 06:54

Java7 の Java.nio.file.Files で ファイルのコピーをしてみる

はじめに

会社では Java で SMB プロトコルをごにょごにょしているというお仕事なので, Java でファイル操作をするような I/F を調べました.

具体的には, フォルダをコピーしたい.

Java7 で Files というライブラリが新たらしく追加された. これが利用できそうなので, 試してみた.

reference

基本

java.nio.file を import.

import java.nio.file.*; 

FileSystems.getDefault ();で ファイルシステムオブジェクトを取得.

// filesystem の取得
FileSystem fileSystem = FileSystems.getDefault ();

ファイル or ディレクトリを表すオブジェクトは Path オブジェクトで示す. 以下のいずれかで取得.

  • fileSystem.getPath ()
  • Paths.get ()
Path fooFile = fileSystem.getPath ("foo.txt");
Path barFile = Paths.get ("bar.txt");

コピーしてみる

Files オブジェクトの copy メソッドを利用する.

public static Path copy (Path source, Path target, CopyOption... options) throws IOException
  • source … コピー元
  • target … コピー先
  • options
    • REPLACE_EXISTING … target が存在すれば上書き
    • COPY_ATTRIBUTES … Attribute もコピー.
    • NOFOLLOW_LINKS … シンポリックリンクはコピーしない.
Files.copy (fooFile, barFile);

reference

コピー

移動

属性の取得

以下でできる.

  • getFileAttributeView ()
  • getFileAttribute ()
  • readFileAttirbute ()

getFileAttributeView (), readFileAttirbute () だと, 指定した FileAttributeView オブジェクトが取得できる.

BasicFileAttributes attrs = Files.getFileAttributeView (barFile, BasicFileAttributeView.class);
BasicFileAttributes attrs = Files.readAttributes (barFile, BasicFileAttributes.class);

getFileAttribute で FileAttirbuteView の個々の属性を指定して情報を取得することができる.

Sample Code

import java.nio.file.*;
import java.nio.file.attribute.*;

public class FilesSample {
    public static void main (String args[]) {
        try {

            // file system
            FileSystem fileSystem = FileSystems.getDefault ();

            // ファイルを表す Path オブジェクトを生成
            Path fooFile = fileSystem.getPath ("foo.txt");
            System.out.println (fooFile);
            Path barFile = Paths.get ("bar.txt");
            System.out.println (barFile);

            // ファイルが存在する場合は削除します
            Files.deleteIfExists (barFile);

            // copy
            Files.copy (fooFile, barFile);

            // 存在チェック
            if (!Files.exists (barFile)) 
                System.out.println ("file not exist");

            // 容量チェック
            if (Files.size (barFile) != Files.size (barFile) ) 
                System.out.println ("file size is not equal");

            BasicFileAttributes attrs = Files.getFileAttributeView (barFile, BasicFileAttributeView.class);
            BasicFileAttributes attrs = Files.readAttributes (barFile, BasicFileAttributes.class);

        } catch (Exception ex) {
            System.out.println (ex);
        }
    }
}

つづき

11 Feb 2015, 02:46

Java で windows のコマンドを実行してフォルダコピー

はじめに

前回の続き.

Java を利用した copy だと, フォルダをコピーすると, 中身をコピーしない.

xcopy を利用.

中身をコピーする方法もあるようだけれども, めんどくさいので, xcopy を利用することにする.

xcopy で ファイルですか, ディレクトリですかと質問されるので, echo F を 先頭につけたいところだが, この方法だと, うまくいかない.

ファイルならば, copy を利用する. フォルダならば, xcopy /i で OK.

Java で windows のコマンドを実行する

processBuilder ライブラリを利用する.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class XCopyOperator {
    public static void main (String args[]) throws IOException, InterruptedException {
        String source = "foo";
        String target = "bar";

        // Process Builder 生成
        // xcopy /e /i source target ディレクトリを再帰的にコピー
        ProcessBuilder pb = new ProcessBuilder ("xcopy", "/e", "/i", source, target);

        // 標準出力と標準エラーをマージする (Defualt false)
        pb.redirectErrorStream (true);

        // プロセス開始
        Process process = pb.start ();

        // プロセス完了待ち合わせ
        process.waitFor ();

        // 結果の出力
        InputStream is = process.getInputStream ();
        printInputStream (is);
    }

    public static void printInputStream (InputStream is) throws IOException {
        BufferedReader br = new BufferedReader (new InputStreamReader (is));
        try {
            for (;;) {
                String line = br.readLine ();
                if (line == null) break;
                System.out.println (line);
            }
        } finally {
            br.close ();
        }
    }
}