Skip to content

Commit 4340073

Browse files
committed
Merge branch 'master' of git@github.com:IanSpratt/fsharpx.git
2 parents e860a07 + 834f2a4 commit 4340073

3 files changed

Lines changed: 58 additions & 12 deletions

File tree

samples/AsyncFileExtensions.fsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22

3-
//#r @"..\build\FSharpx.Core.dll"
4-
#r @"C:\Users\Ian\Documents\GitHub\Ian144\fsharpx\build\debug\FSharpx.Core.dll"
3+
#r @"..\build\FSharpx.Core.dll"
4+
55

66
open Microsoft.FSharp.Control
77

@@ -16,15 +16,27 @@ let asyncWriteA = System.IO.File.AsyncWriteAllLines(@"c:\tmp\a.txt", lines)
1616
let asyncWriteB = System.IO.File.AsyncWriteAllLines(@"c:\tmp\b.txt", lines)
1717
let asyncWriteC = System.IO.File.AsyncWriteAllLines(@"c:\tmp\c.txt", lines)
1818
let asyncWriteD = System.IO.File.AsyncWriteAllLines(@"c:\tmp\d.txt", lines)
19-
let asyncWriteE = System.IO.File.AsyncWriteAllText( @"c:\tmp\e.txt", "this is some text")
19+
let asyncWriteE = System.IO.File.AsyncWriteAllText( @"c:\tmp\e.txt", "this is some text\n")
2020

21-
printfn "async write all lines begining"
21+
printfn "async write all lines beginning"
2222

23-
[|asyncWriteA; asyncWriteB; asyncWriteC; asyncWriteD; asyncWriteE|]
23+
[|asyncWriteA; asyncWriteB; asyncWriteC; asyncWriteD; asyncWriteE|]
2424
|> Async.Parallel
2525
|> Async.RunSynchronously
2626
|> ignore
2727

2828

29+
let asyncAppendA = System.IO.File.AsyncAppendAllLines(@"c:\tmp\a.txt", lines)
30+
let asyncAppendB = System.IO.File.AsyncAppendAllLines(@"c:\tmp\b.txt", lines)
31+
let asyncAppendC = System.IO.File.AsyncAppendAllLines(@"c:\tmp\c.txt", lines)
32+
let asyncAppendD = System.IO.File.AsyncAppendAllLines(@"c:\tmp\d.txt", lines)
33+
let asyncAppendE = System.IO.File.AsyncAppendAllText( @"c:\tmp\e.txt", "this is some more text\n")
34+
35+
36+
[|asyncAppendA;asyncAppendB;asyncAppendC;asyncAppendD; asyncAppendE|]
37+
|> Async.Parallel
38+
|> Async.RunSynchronously
39+
|> ignore
40+
2941

30-
printfn "async write all lines complete"
42+
printfn "async append all lines complete"

src/FSharpx.Core/AsyncOperations.fs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ namespace Microsoft.FSharp.Control
9696
do! Async.SwitchToThreadPool ()
9797
return res }
9898

99+
100+
let private LinesToBytes ((lines:string array), encoder) =
101+
use memStrm = new System.IO.MemoryStream()
102+
use sWriter = new System.IO.StreamWriter(memStrm, encoder)
103+
lines |> Array.iter (fun line -> sWriter.WriteLine(line))
104+
do sWriter.Flush()
105+
memStrm.ToArray()
99106

100107
type System.IO.File with
101108
static member AsyncOpenText(path) = UnblockViaNewThread (fun () -> System.IO.File.OpenText(path))
@@ -135,6 +142,7 @@ namespace Microsoft.FSharp.Control
135142

136143
#if FX_NO_FILE_OPTIONS
137144
#else
145+
138146
// Aims to take advantage of IO completion ports using FileStream.AsyncWrite and FileOptions.Asynchronous, so no FX_NO_FILE_OPTIONS version
139147
static member AsyncWriteAllBytes(path, bytes) =
140148
let bufferSize = 4096 // as per File.WriteAllBytes
@@ -157,14 +165,37 @@ namespace Microsoft.FSharp.Control
157165
static member AsyncWriteAllLines(path, (lines:string array), ?encoder) =
158166
let enc = match encoder with Some e -> e | None -> System.Text.Encoding.Default
159167
async{
160-
use memStrm = new System.IO.MemoryStream()
161-
use sWriter = new System.IO.StreamWriter(memStrm, enc)
162-
lines |> Array.iter (fun line -> sWriter.WriteLine(line))
163-
do sWriter.Flush()
164-
let bs = memStrm.ToArray()
168+
let bs = LinesToBytes (lines, enc)
165169
return! System.IO.File.AsyncWriteAllBytes(path, bs)
166170
}
167171

172+
// Aims to take advantage of IO completion ports using FileStream.AsyncWrite and FileOptions.Asynchronous, so no FX_NO_FILE_OPTIONS version
173+
static member AsyncAppendAllBytes(path, bytes) =
174+
let bufferSize = 4096 // as per File.WriteAllBytes
175+
async{
176+
use! fs = System.IO.File.AsyncOpen( path, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.Read, bufferSize, System.IO.FileOptions.Asynchronous)
177+
let! ret = fs.AsyncWrite bytes
178+
return ret
179+
}
180+
181+
static member AsyncAppendAllText(path, (txt:string), ?encoder) =
182+
let enc = match encoder with Some e -> e | None -> System.Text.Encoding.Default
183+
async{
184+
let bs = enc.GetBytes txt
185+
return! System.IO.File.AsyncAppendAllBytes(path, bs)
186+
}
187+
188+
// Different memory profile to File.AppendAllLines, converts all lines to a byte[] before doing any writing, then a single write op.
189+
// Not good for writing huge files, but writing one line at a time, as per File.AppendAllLines has its own issues,
190+
// e.g. sequential application of async IO (so lines are written in order)
191+
static member AsyncAppendAllLines(path, (lines:string array), ?encoder) =
192+
let enc = match encoder with Some e -> e | None -> System.Text.Encoding.Default
193+
async{
194+
let bs = LinesToBytes (lines, enc)
195+
return! System.IO.File.AsyncAppendAllBytes(path, bs)
196+
}
197+
198+
168199

169200
#endif
170201

src/FSharpx.Core/AsyncOperations.fsi

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,12 @@ namespace Microsoft.FSharp.Control
6565

6666
// Aims to take advantage of IO completion ports using FileStream.AsyncWrite and FileOptions.Asynchronous, so no FX_NO_FILE_OPTIONS version
6767
static member AsyncWriteAllBytes: path:string * bytes:byte array -> Async<unit>
68-
6968
static member AsyncWriteAllText: path:string * txt:string * ?encoder:System.Text.Encoding -> Async<unit>
7069
static member AsyncWriteAllLines: path:string * lines:string array * ?encoder:System.Text.Encoding -> Async<unit>
70+
static member AsyncAppendAllBytes: path:string * bytes:byte array -> Async<unit>
71+
static member AsyncAppendAllText: path:string * txt:string * ?encoder:System.Text.Encoding -> Async<unit>
72+
static member AsyncAppendAllLines: path:string * lines:string array * ?encoder:System.Text.Encoding -> Async<unit>
73+
7174
#endif
7275

7376
#if FX_NO_WEB_REQUESTS

0 commit comments

Comments
 (0)