@@ -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
0 commit comments