スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門基本編落穂拾い その46 List.collect

今回はList.collectを紹介します。
まずは型から
> List.collect ;;
val it : (('a -> 'b list) -> 'a list -> 'b list) //#1
 
'a型の要素から'b型のリストの写像と、'a型のリストseedLstを与えると、seedLstの各要素に写像を作用させて、それぞれの場合の結果のリストを繋げて、一つのリストにして返してくれます。
 

> List.collect (fun x -> [x;x+1;x+2]) [0;10;20];;
val it : int list = [0; 1; 2; 10; 11; 12; 20; 21; 22]
 
これは「xから[x;x+1;x+2]という3つの要素をもつリストを作り出す関数」を0,10,20それぞれに作用させて、その結果の[0;1;2],[10,11,12],[20,21,22]を繋げて一つのリストにして返してくれています。
普通のmapでは、次のようになるところです。
 
> List.map (fun x -> [x;x+1;x+2]) [0;10;20];;
val it : int list list = [[0; 1; 2]; [10; 11; 12]; [20; 21; 22]]
 
ここで#1で'bを'aとしてみます。
(('a -> 'a list) -> 'a list -> 'a list) //#2
#2は非常に扱いやすい形で、('a  ->'a list)の形の関数をList.collect に部分適用すれば、これは
'a list -> 'a list 型の関数になるので、繰り返し適用していけます。
 

 
> let g1 = List.collect (fun x -> [x;2*x])
let g2=  List.collect (fun x -> [x+1;x+2;x+3])
let g3 = List.collect (fun x -> [3*x;3*x+1]);;
 
val g1 : (int list -> int list)
val g2 : (int list -> int list)
val g3 : (int list -> int list)
 
> [1] |> g1 |> g2 |> g3;;
val it : int list = [6; 7; 9; 10; 12; 13; 9; 10; 12; 13; 15; 16]
 
樹形図のようなものをイメージしてもらうと分かりやすいかもしれません。
 
1___1___2___6
____________7
________3___9
____________10
________4___12
____________13
____2___3___9
____________10
________4___12
____________13
________5___15
____________16
 
それではList.collectを利用して「文字列を総当たりで連結する関数」を定義してみます。
次のような動きをする関数です。
 
> connString [["A";"B";"C"];["1";"2"];["&";"$"]] ;;
val it : string list =
  ["A1&"; "A1$"; "A2&"; "A2$"; "B1&"; "B1$"; "B2&"; "B2$"; "C1&"; "C1$"; "C2&";
   "C2$"]
 
定義は次になります。
 
> let connString baseList =
        
    let addStr (a:string) (b:string) = a + b
    let f (v:string list) = (fun (k:string) -> List.map (addStr k) v)
       
    List.reduce (fun (s:string list) (x:string list) ->
                    let g = f s
                    x |> List.collect g )
                (List.rev baseList);;
 
val connString : string list list -> string list
 
使用例
 
> connString [["img"];["1";"2";"3"];["."];["1";"2";"3";"4";"5";"6"]];;
val it : string list =
  ["img1.1"; "img1.2"; "img1.3"; "img1.4"; "img1.5"; "img1.6"; "img2.1";
   "img2.2"; "img2.3"; "img2.4"; "img2.5"; "img2.6"; "img3.1"; "img3.2";
   "img3.3"; "img3.4"; "img3.5"; "img3.6"]
   
では同様に「リストを総当たりで連結する関数」を書いてみます。
 
> let connList (baseList :list<list<list<'a>>>) =
   
   let add2 (a:list<'a>) (l:list<'a>) = a @ l
   let f (v:list<list<'a>>) = (fun (k:list<'a>) -> (List.map (add2 k) v)) 
       
   List.reduce (fun (s:list<list<'a>>) (x:list<list<'a>>) ->
                    let g = f s
                    x |> List.collect g )
                (List.rev baseList);;
 
val connList : 'a list list list -> 'a list list
 
使用例
 
> connList [[["a"];["b"]];[["c"];["d"]]];;
val it : string list list = [["a"; "c"]; ["a"; "d"]; ["b"; "c"]; ["b"; "d"]]
 
> connList [[["a";"x"];["b"]];[["c"];["d"]]];;
val it : string list list =
  [["a"; "x"; "c"]; ["a"; "x"; "d"]; ["b"; "c"]; ["b"; "d"]]
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

F#入門基本編落穂拾い その45 ファイル、フォルダの監視

ファイル、フォルダの変更を監視するには、System.IO.FileSystemWatcherクラスのインスタンスを利用します。
ひとつインスタンスを生成してみます。
 
> let fsw = new System.IO.FileSystemWatcher();;
val fsw : System.IO.FileSystemWatcher = System.IO.FileSystemWatcher
 
> fsw;;
val it : System.IO.FileSystemWatcher =
  System.IO.FileSystemWatcher
    {Container = null;
     EnableRaisingEvents = false;
     Filter = "*.*";
     IncludeSubdirectories = false;
     InternalBufferSize = 8192;
     NotifyFilter = FileName, DirectoryName, LastWrite;
     Path = "";
     Site = null;
     SynchronizingObject = null;}
 
特に重要なのはFilterとIncludeSubdirectoriesとNotifyFilterとPathとEnableRaisingEventsです。
 
○Pathで監視するフォルダを設定します。

 
> fsw.Path <- @"s:\BlogTest" ;;
val it : unit = ()
 
○NotifyFilterでは、どのような変更に目を光らすかを指定します。
System.IO.NotifyFilters列挙体で定義します。
 FileName ファイルの名前。 
 DirectoryName     ディレクトリ名。 
 Attributes     ファイルまたはフォルダーの属性。 
 Size             ファイルまたはフォルダーのサイズ。 
 LastWrite         ファイルまたはフォルダーへの最終書き込み日付。 
 LastAccess     ファイルまたはフォルダーを最後に開いた日付。 
 CreationTime     ファイルまたはフォルダーが作成された時刻。 
 Security         ファイルまたはフォルダーのセキュリティ設定。 
 
デフォルトでは、FileName, DirectoryName, LastWriteとなっています。
たとえば次のように指定します。
 
> fsw.NotifyFilter <- NotifyFilters. LastWrite ||| NotifyFilters.FileName;;
val it : unit = ()
 
○Filterプロパティは、指定フォルダで監視するファイルを指定する場合に使用します。
なお、この指定にはワイルドカード(*)が使用できます。
 
フィルタ文字列の例
 
*.*
 すべてのファイル (既定)。空の文字列 ("") を指定しても、すべてのファイルがウォッチ(監視)されます。
 
*.txt
 拡張子が "txt" のすべてのファイル。
 
*sf2.txt
 ファイル名が "sf2" で終わり、拡張子が "txt" のすべてのファイル。
 
sf2.txt
 sf2.txtのみをウォッチします。
 
○IncludeSubdirectoriesプロパティをtureにすると、サブフォルダも監視対象となります。
 
○EnableRaisingEventsプロパティをtrueに設定すると監視処理が開始されます。監視が不要な場合には、一時的にこのプロパティをfalseに設定すればよいです。
 
イベントおよびイベントの発生するタイミングは次の通りです。
 
OnCreated ファイルまたはディレクトリが作成されたとき 
OnDeleted ファイルまたはディレクトリが削除されたとき 
OnRenamed ファイルまたはディレクトリの名前が変更されたとき 
OnChanged ・サイズ・属性・最終書き込み日時・最終アクセス日時・セキュリティ設定 以下のいずれかが変更されたとき
 
それでは、例を一つs:\BlogTestフォルダ以下で、拡張子がtxtのファイルの作成、削除、名前の変更、LastWrite時刻とLastAccess時刻の変更を監視するようにしてみます。
 
 
open System.IO
let fsw = new System.IO.FileSystemWatcher() 
 
fsw.Path <- @"s:\BlogTest" 
fsw.IncludeSubdirectories <- true 
 
fsw.NotifyFilter <- NotifyFilters.LastAccess ||| NotifyFilters.LastWrite 
                    ||| NotifyFilters.FileName
 
//拡張子がtxtのものだけ監視する
fsw.Filter <- "*.txt"
 
[fsw.Changed ; fsw.Created ;fsw.Deleted]
|>  List.map (Observable.add (fun (e:FileSystemEventArgs) -> printfn "%A" e.ChangeType))
|> ignore
 
fsw.Renamed.Add(fun e -> printfn "%A renamed to %A" e.OldFullPath e.FullPath)
fsw.EnableRaisingEvents <- true
 
(実行結果例)名前を変更した場合
"s:\BlogTest\SF1\SF1SF1\SF1SF1.txt" renamed to "s:\BlogTest\SF1\SF1SF1\SF1SF11.txt"
 
なお組み合わせによっては一つのファイル操作で複数のイベントが発火される場合がありますので、注意が必要です。
 
 
FileSystemEventArgs についてはhttp://msdn.microsoft.com/ja-jp/library/system.io.filesystemeventargs(VS.80).aspxを参照ください。

なお2010/7/23までの目次はこちらにあります。

テーマ : プログラミング
ジャンル : コンピュータ

F#入門基本編落穂拾い その44 ファイル、フォルダ処理(3)

今回はDiscriminated unionを利用して、ファイル、フォルダを一度メモリ上に保存してから、これを対象として、関数を適用することを考えてみます。ファイル、フォルダについて、それぞれFileInfo,DirectoryInfoを情報として付加しておくことにします。
次のように定義します。
 
open System.IO
 
type Entry =
  | File of System.IO.FileInfo
  | Dir of System.IO.DirectoryInfo * list<Entry>
 
実際のファイルフォルダからEntry型の値を生成する関数を定義します。
 
let rec mkEntry(path : string)  =
 
    if System.IO.File.Exists (path) then //pathがファイル名を表す場合
        File(new System.IO.FileInfo(path))
 
    else //path がディレクトリ名の場合
       let  subEntries =
                [for entry in Directory.GetFileSystemEntries(path) do
                    yield mkEntry(entry)]
       Dir(new System.IO.DirectoryInfo(path) ,subEntries)
 
val mkEntry : string -> Entry
 
次のようなフォルダに適用してみます。

347-1.jpg 
 
 
なおそれぞれのフォルダ内にはフォルダ名と同名で拡張子がtxtのテキストファイルが保存されているとします。(前回までと同じものです。)
 
> let t = mkEntry @"s:\BlogTest";;
 
val t : Entry =
  Dir
    (s:\BlogTest,
     [Dir
        (s:\BlogTest\SF1,
         [File s:\BlogTest\SF1\SF1.txt;
          Dir
            (s:\BlogTest\SF1\SF1SF1,
             [File s:\BlogTest\SF1\SF1SF1\SF1SF1.txt;
              Dir
                (s:\BlogTest\SF1\SF1SF1\SF1SF1SF1,
                 [File s:\BlogTest\SF1\SF1SF1\SF1SF1SF1\SF1SF1SF1.txt]);
              Dir
                (s:\BlogTest\SF1\SF1SF1\SF1SF1SF2,
                 [File s:\BlogTest\SF1\SF1SF1\SF1SF1SF2\SF1SF1SF2.txt])]);
          Dir
            (s:\BlogTest\SF1\SF1SF2,[File s:\BlogTest\SF1\SF1SF2\SF1SF2.txt])]);
      Dir
        (s:\BlogTest\SF2,
         [File s:\BlogTest\SF2\SF2.txt;
          Dir
            (s:\BlogTest\SF2\SF2SF1,[File s:\BlogTest\SF2\SF2SF1\SF2SF1.txt])])])
            
            
さて、それではこれに対して関数を適用して、「ファイルの大きさの和」や、「ファイル名一覧」、「一番最近にアクセスされたファイルまたはフォルダ」などを求めてみたいと思います。ひとつひとつ関数を定義するのではなく、Entry型の値の上をtraverse(渡り歩く)していき、値をまとめるという役目をする関数を定義しておき、これを利用することにします。
なお、調べていくのはファイルの場合はFileInfoで、ディレクトリの場合はDirectoryInfoです。型が違うので、ワンクッションいれて同じ型に変換し(下の定義ではgfとgd)それを対象に処理していくようにしています。
 
> let rec holdEntry f acc  (gf:FileInfo -> 'a) (gd:DirectoryInfo -> 'a) (node:Entry) =
    match node with
    | File(fi) -> 
            (f acc (gf fi))
    | Dir (di,entries) ->
            let subAcc = List.fold (fun acc2 x -> holdEntry f acc2  gf gd x) acc entries
            (f subAcc (gd di));;
 
val holdEntry :
  ('a -> 'a0 -> 'a) ->
    'a -> (FileInfo -> 'a0) -> (DirectoryInfo -> 'a0) -> Entry -> 'a
 
 
では使ってみます。
 
(ファイルの大きさの合計を求める)
 
> holdEntry (+) 0L (fun  fi -> fi.Length) (fun _ -> 0L) t;;
 
val it : int64 = 42L
 
(ディレクトリ(フォルダ)名の一覧を求める)
 
> holdEntry (fun acc (name:option<string>) ->if name.IsSome then name.Value :: acc else acc)
          []
          (fun _ -> None) 
          (fun di  -> Some(di.FullName) ) 
           t;;
 
val it : string list =
  ["s:\BlogTest"; "s:\BlogTest\SF2"; "s:\BlogTest\SF2\SF2SF1";
   "s:\BlogTest\SF1"; "s:\BlogTest\SF1\SF1SF2"; "s:\BlogTest\SF1\SF1SF1";
   "s:\BlogTest\SF1\SF1SF1\SF1SF1SF2"; "s:\BlogTest\SF1\SF1SF1\SF1SF1SF1"]
 
(ファイル名とその大きさの一覧を求める)
 
> holdEntry (fun acc (n_l:option<string*int64>) ->if n_l.IsSome then n_l.Value :: acc else acc)
          []
          (fun fi -> Some((fi.Name,fi.Length))) 
          (fun _  -> None) 
           t;;
 
val it : (string * int64) list =
  [("SF2SF1.txt", 6L); ("SF2.txt", 3L); ("SF1SF2.txt", 6L);
   ("SF1SF1SF2.txt", 9L); ("SF1SF1SF1.txt", 9L); ("SF1SF1.txt", 6L);
   ("SF1.txt", 3L)]
 
(ファイルまたはフォルダが一番最近にアクセスされた時刻)
 
> holdEntry (fun acc (dt:System.DateTime) ->
                if acc = None then Some(dt)
                else
                    if System.DateTime.Compare(dt,acc.Value) < 0 then acc
                    else Some(dt))
          None
          (fun fi -> fi.LastAccessTime) 
          (fun di  ->di.LastAccessTime) 
           t;;
 
val it : System.DateTime option =
  Some 2010/07/06 7:59:05 {Date = 2010/07/06 0:00:00;
                           Day = 6;
                           DayOfWeek = Tuesday;
                           DayOfYear = 187;
                           Hour = 7;
                           Kind = Local;
                           Millisecond = 806;
                           Minute = 59;
                           Month = 7;
                           Second = 5;
                           Ticks = 634139999458066406L;
                           TimeOfDay = 07:59:05.8066406;
                           Year = 2010;}
 
 
(一番最近にアクセスされたファイルまたはフォルダ名とその時刻)
 
> holdEntry (fun acc (n_d:string*System.DateTime) ->
                if acc = None then Some(n_d)
                else
                    if System.DateTime.Compare(snd n_d ,snd acc.Value) < 0 then acc
                    else Some(n_d))
          None
          (fun fi -> (fi.Name,fi.LastAccessTime)) 
          (fun di  ->(di.Name,di.LastAccessTime)) 
          t;;
          
val it : (string * System.DateTime) option =
  Some ("SF1SF1", 2010/07/06 7:59:05 {Date = 2010/07/06 0:00:00;
                                      Day = 6;
                                      DayOfWeek = Tuesday;
                                      DayOfYear = 187;
                                      Hour = 7;
                                      Kind = Local;
                                      Millisecond = 806;
                                      Minute = 59;
                                      Month = 7;
                                      Second = 5;
                                      Ticks = 634139999458066406L;
                                      TimeOfDay = 07:59:05.8066406;
                                      Year = 2010;})
 

テーマ : プログラミング
ジャンル : コンピュータ

F#入門基本編落穂拾い その43 ファイル、フォルダ処理(2)

今回はファイル処理をまとめておきたいと思います。
 
サンプルとして下のような構成のフォルダが(Sドライブにあるとします。(前回と同じものです。) 
 
347-1.jpg 
 
 
なおそれぞれのフォルダ内にはフォルダ名と同名で拡張子がtxtのテキストファイルが保存されているとします。
たとえばSF1SF1フォルダの中身は次のようになっており 
 
347-2.jpg 
 
SF1SF1SF1フォルダの中身は次のようになっています。 
 
347-3.jpg 
 
それではまずファイルの存在の確認から、これは次のようにします。
 
> System.IO.File.Exists(@"s:\BlogTest\SF1\SF1.txt") ;;
val it : bool = true
 
ディレクトリ(フォルダ)については、DirectoryInfo型の値が存在し、詳細な情報を得ることができました。同様に、ファイルについてはFileInfo型の値が定義されています。
 
> let fi = new System.IO.FileInfo(@"s:\BlogTest\SF1\SF1.txt");;
val fi : System.IO.FileInfo = s:\BlogTest\SF1\SF1.txt
 
> fi;;
val it : System.IO.FileInfo =
  s:\BlogTest\SF1\SF1.txt {Attributes = Archive;
                           CreationTime = 2010/07/05 19:26:05;
                           CreationTimeUtc = 2010/07/05 10:26:05;
                           Directory = s:\BlogTest\SF1;
                           DirectoryName = "s:\BlogTest\SF1";
                           Exists = true;
                           Extension = ".txt";
                           FullName = "s:\BlogTest\SF1\SF1.txt";
                           IsReadOnly = false;
                           LastAccessTime = 2010/07/05 19:26:05;
                           LastAccessTimeUtc = 2010/07/05 10:26:05;
                           LastWriteTime = 2010/07/05 19:23:58;
                           LastWriteTimeUtc = 2010/07/05 10:23:58;
                           Length = 3L;
                           Name = "SF1.txt";}
 
Length がサイズで、3バイトという意味という意味になります。(Int64型です。)
 
ファイルの属性(「隠しファイルであるか」等)を調べるには以下のようにします。
 
> let fa = System.IO.File.GetAttributes(@"s:\BlogTest\SF1\SF1.txt");;
 
val fa : System.IO.FileAttributes = Archive
 
この値とSystem.IO.FileAttributes.Hiddenとの論理和をとり、それで変化しなければ、「その属性をもつ」ということになります。
 
(例)
○隠しファイルかどうかを調べる
> (fa &&& System.IO.FileAttributes.Hidden) =  System.IO.FileAttributes.Hidden;;
val it : bool = false
○読み取り専用かどうかを調べる
> (fa &&& System.IO.FileAttributes.ReadOnly) =  System.IO.FileAttributes.ReadOnly  ;;
val it : bool = false
 
その他の属性についてはhttp://msdn.microsoft.com/ja-jp/library/system.io.fileattributes.aspx
を参照してください。
 
また簡単なテキストファイルの読み書きについては 「テキストファイルの読み込み」を参照してください。
 
次はファイルのコピーです。これはSystem.IO.File.Copy(コピー元,コピー先)で、行えますが、コピー先ファイルが既に存在する場合は例外が発生します。コピー先のディレクトリ(フォルダ)が存在しない場合も例外が発生します。
System.IO.File.Copy(コピー元,コピー先,true)とすると上書きコピーができます。
 
移動はSystem.IO.File.Move(移動元,移動先)で実行できます。コピーして、もとのファイルを削除するのと同等です。
 
削除はSystem.IO.File.Delete(削除するファイル)でおこないます。存在しないファイルを削除しようとしても例外は発生しません。)
 
あるフォルダ以下のすべてのファイルの一覧を得るには、例えば次のようにします。
 
> let rec filesUnder (basePath : string) =
    [|
        yield! System.IO.Directory.GetFiles(basePath)
        let sDirs = System.IO.Directory.GetDirectories (basePath)
        for subDir in sDirs do
            yield! filesUnder subDir
     |];;
 
val filesUnder : string -> string []
 
(実行例)
 
> filesUnder @"s:\BlogTest";;
 
val it : string [] =
  [|"s:\BlogTest\SF1\SF1.txt"; "s:\BlogTest\SF1\SF1SF1\SF1SF1.txt";
    "s:\BlogTest\SF1\SF1SF1\SF1SF1SF1\SF1SF1SF1.txt";
    "s:\BlogTest\SF1\SF1SF1\SF1SF1SF2\SF1SF1SF2.txt";
    "s:\BlogTest\SF1\SF1SF2\SF1SF2.txt"; "s:\BlogTest\SF2\SF2.txt";
    "s:\BlogTest\SF2\SF2SF1\SF2SF1.txt"|]
    
 
 
> filesUnder @"s:\BlogTest\SF1\SF1SF1";;
 
val it : string [] =
  [|"s:\BlogTest\SF1\SF1SF1\SF1SF1.txt";
    "s:\BlogTest\SF1\SF1SF1\SF1SF1SF1\SF1SF1SF1.txt";
    "s:\BlogTest\SF1\SF1SF1\SF1SF1SF2\SF1SF1SF2.txt"|]
 
あと少しパス関連のメソッドをメモしておきます。
 
○ファイルパスを結合する
 
> System.IO.Path.Combine(@"s:\BlogTest\SF1", "SF1.txt");;
val it : string = "s:\BlogTest\SF1\SF1.txt"
 
> [@"s:\BlogTest";"SF1";"SF1.txt"]
  |> List.reduce (fun s x  -> System.IO.Path.Combine(s,x)) ;;
val it : string = "s:\BlogTest\SF1\SF1.txt"
 
○ファイルパスからファイル名を抜き出す
 
> System.IO.Path.GetFileName(@"s:\BlogTest\SF1\SF1.txt");;
val it : string = "SF1.txt"
 
○ファイルパスから拡張子を含まないファイル名を抜き出す
 
> System.IO.Path.GetFileNameWithoutExtension(@"s:\BlogTest\SF1\SF1.txt");;
val it : string = "SF1"
 
○ファイルパスからディレクトリ (フォルダ) を抜き出す
 
> System.IO.Path.GetDirectoryName(@"s:\BlogTest\SF1\SF1.txt");;
val it : string = "s:\BlogTest\SF1"
 
○ファイルパスから拡張子を抜き出す
 
> System.IO.Path.GetExtension(@"s:\BlogTest\SF1\SF1.txt");;
val it : string = ".txt"
 
> System.IO.Path.ChangeExtension(@"s:\BlogTest\SF1\SF1.txt","log");;
val it : string = "s:\BlogTest\SF1\SF1.log"
 
○拡張子を変更する
 
> System.IO.Path.ChangeExtension(@"s:\BlogTest\SF1\SF1.txt","log");;
val it : string = "s:\BlogTest\SF1\SF1.log"
 
○拡張子を取り去る
 
> System.IO.Path.ChangeExtension(@"s:\BlogTest\SF1\SF1.log",null);;
val it : string = "s:\BlogTest\SF1\SF1"
 
○存在する論理ドライブ名をすべて取得する
 
>  System.IO.Directory.GetLogicalDrives();;
val it : string [] =
  [|"C:\"; "E:\"; "F:\"; "G:\"; "H:\"; "I:\"; "J:\"; "S:\"|]
  

テーマ : プログラミング
ジャンル : コンピュータ

F#入門基本編落穂拾い その42 ファイル、フォルダ処理(1)

今回はフォルダ処理をまとめておきたいと思います。
 
サンプルとして下のような構成のフォルダがあるとします。(Sドライブにあるとします。) 
 
347-1.jpg 
 
 
なおそれぞれのフォルダ内にはフォルダ名と同名で拡張子がtxtのテキストファイルが保存されているとします。
たとえばSF1SF1フォルダの中身は次のようになっており 
 
347-2.jpg 
 
SF1SF1SF1フォルダの中身は次のようになっています。 
 
347-3.jpg 

 
それではまずフォルダの存在の確認から、これは次のようにします。
 
> System.IO.Directory.Exists(@"s:\BlogTest\SF1");;
 
val it : bool = true
 
("s:\BlogTest\SF1" 等をフォルダのパス文字列といいます。)
 
つぎにフォルダの作成です。
 
> System.IO.Directory.CreateDirectory(@"s:\BlogTest\SF3");;
 
val it : System.IO.DirectoryInfo =
  SF3 {Attributes = Directory;
       CreationTime = 2010/07/05 19:39:02;
       CreationTimeUtc = 2010/07/05 10:39:02;
       Exists = true;
       Extension = "";
       FullName = "s:\BlogTest\SF3";
       LastAccessTime = 2010/07/05 19:39:02;
       LastAccessTimeUtc = 2010/07/05 10:39:02;
       LastWriteTime = 2010/07/05 19:39:02;
       LastWriteTimeUtc = 2010/07/05 10:39:02;
       Name = "SF3";
       Parent = BlogTest;
 
ご覧の通り新しいDirectoryが作成された上で、DirectoryInfo型の値が返り値として帰ってきます。
 
既存のフォルダのDirectoryInfoを得るには次のようにします。
 
> let di = new System.IO.DirectoryInfo(@"s:\BlogTest\SF3")  ;;
val di : System.IO.DirectoryInfo = s:\BlogTest\SF3
 
> di;;
val it : System.IO.DirectoryInfo =
  s:\BlogTest\SF3 {Attributes = Directory;
                   CreationTime = 2010/07/05 19:39:02;
                   CreationTimeUtc = 2010/07/05 10:39:02;
                   Exists = true;
                   Extension = "";
                   FullName = "s:\BlogTest\SF3";
                   LastAccessTime = 2010/07/05 19:39:02;
                   LastAccessTimeUtc = 2010/07/05 10:39:02;
                   LastWriteTime = 2010/07/05 19:39:02;
                   LastWriteTimeUtc = 2010/07/05 10:39:02;
                   Name = "SF3";
                   Parent = BlogTest;
                   Root = s:\;}
 
次はフォルダの移動です。(移動といっても同時に名前の変更もできます。)
 
これは
System.IO.Directory.Move(移動されるフォルダのパス文字列,移動先フォルダのパス文字列)
で行います。
「移動先フォルダ」が作成され、移動元フォルダの中身が移動され、移動元フォルダが消去される。という作用をします。 
 
347-4.jpg 

 
> System.IO.Directory.Move(@"s:\BlogTest\SF3",@"s:\BlogTest\SF1\SF1SF1\new_SF3");;
val it : unit = () 
 
347-5.jpg 
 
フォルダの削除は次のようにします
ただし、フォルダの中身が空でないとエラーが発生します。
 
> System.IO.Directory.Delete(@"s:\BlogTest\SF1\SF1SF1\new_SF3");;
val it : unit = ()
 
アプリケーションの現在のカレントディレクトリをを取得するにはDirectoryクラスのGetCurrentDirectoryメソッドを使用します。またカレントディレクトリをを設定するにはSetCurrentDirectoryメソッドを使用します。 カレントディレクトリとは、ファイルパスをドライブ文字から指定しなかった場合に開始位置となる場所のことです。)
 
> System.IO.Directory.GetCurrentDirectory();;
val it : string = "C:\Users\T_GYOUTEN\AppData\Local\Temp"
 
指定したフォルダ内のサブフォルダを取得するにはSystem.IO.Directory.GetDirectoriesを利用します。
 
> System.IO.Directory.GetDirectories (@"s:\BlogTest\SF1") ;;
val it : string [] = [|"s:\BlogTest\SF1\SF1SF1"; "s:\BlogTest\SF1\SF1SF2"|]
 
存在しないときは
 
> System.IO.Directory.GetDirectories (@"s:\BlogTest\SF1\SF1SF1\SF1SF1SF1") ;;
val it : string [] = [||]
 
となり要素数が0の配列が帰ってきます。
 
ご覧の通り、フォルダ内のサブフォルダ(のパス)が取得されており、それより下の階層にあるサブフォルダは取得されていません。
下の階層にあるサブフォルダは取得するには再帰を用いるのが一般的です。
 
> let rec dirsUnder (path : string) =
    [|
        let sDirs = System.IO.Directory.GetDirectories (path)
        yield! sDirs
        for subDir in sDirs do
            yield! dirsUnder subDir
     |];;
 
val dirsUnder : string -> string []
 
もしyield!の部分がyieldなら、配列の要素がはいるべき部分に配列が返ってくることにになります。[| ".." ; [| "  "|]; ...|]という形となり、配列の要素が同じ型でなくなるので、エラーでコンパイルできません。yield!は返ってきた配列を、[| |]をはずして、元の配列の一部にしてくれます。一段下の段階のものを、上に引き戻して処理してくれるので、再帰の結果をフラット化するのによく用いられます。
 
実行例
> dirsUnder  (@"s:\BlogTest") ;;
val it : string [] =
  [|"s:\BlogTest\SF1"; "s:\BlogTest\SF2"; "s:\BlogTest\SF1\SF1SF1";
    "s:\BlogTest\SF1\SF1SF2"; "s:\BlogTest\SF1\SF1SF1\SF1SF1SF1";
    "s:\BlogTest\SF1\SF1SF1\SF1SF1SF2"; "s:\BlogTest\SF2\SF2SF1"|]
 
それではこれを用いてBlogTestフォルダで、作成時刻が2010/07/05 18:19:00以降のフォルダだけを抜き出してみます。
 
> dirsUnder  (@"s:\BlogTest")  
  |> Array.map (fun path -> new System.IO.DirectoryInfo (path))
  |> Array.filter(fun di -> System.DateTime.Compare(di.CreationTime,criTime) > 0)
  |> Array.map (fun di -> (di.FullName))     ;;
 
val it : string [] =
  [|"s:\BlogTest\SF1\SF1SF2"; "s:\BlogTest\SF1\SF1SF1\SF1SF1SF1";
    "s:\BlogTest\SF1\SF1SF1\SF1SF1SF2"; "s:\BlogTest\SF2\SF2SF1"|]
    
 
なおDirectoryInfo型の値はインスタンスメソッドGetDirectories()をもっていて、これを利用しても、このディレクトリに含まれるディレクトリの一覧を得ることができます。

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。