Skip to content

Commit 83ea729

Browse files
authored
FileStream F# snippets (#8873)
1 parent 8dcb4d4 commit 83ea729

File tree

24 files changed

+645
-0
lines changed

24 files changed

+645
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module example
2+
//<SNIPPET1>
3+
open System
4+
open System.IO;
5+
open System.Text
6+
open System.Security.AccessControl;
7+
8+
try
9+
// Create a file and write data to it.
10+
11+
// Create an array of bytes.
12+
let messageByte = Encoding.ASCII.GetBytes "Here is some data."
13+
// Specify an access control list (ACL)
14+
let fs = FileSecurity()
15+
16+
FileSystemAccessRule(@"DOMAINNAME\AccountName", FileSystemRights.ReadData, AccessControlType.Allow)
17+
|> fs.AddAccessRule
18+
// Create a file using the FileStream class.
19+
let fWrite = new FileStream("test.txt", FileMode.Create, FileSystemRights.Modify, FileShare.None, 8, FileOptions.None, fs)
20+
21+
// Write the number of bytes to the file.
22+
byte messageByte.Length
23+
|> fWrite.WriteByte
24+
25+
// Write the bytes to the file.
26+
fWrite.Write(messageByte, 0, messageByte.Length);
27+
28+
// Close the stream.
29+
fWrite.Close();
30+
31+
// Open a file and read the number of bytes.
32+
33+
let fRead = new FileStream("test.txt", FileMode.Open)
34+
35+
// The first byte is the string length.
36+
let length = fRead.ReadByte() |> int
37+
38+
// Create a new byte array for the data.
39+
let readBytes = Array.zeroCreate length
40+
41+
// Read the data from the file.
42+
fRead.Read(readBytes, 0, readBytes.Length);
43+
44+
// Close the stream.
45+
fRead.Close();
46+
47+
// Display the data.
48+
printfn $"{Encoding.ASCII.GetString readBytes}"
49+
printfn "Done writing and reading data."
50+
51+
with e ->
52+
printfn $"{e}"
53+
//</SNIPPET1>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net48</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="example.fs" />
9+
</ItemGroup>
10+
</Project>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module example
2+
//<SNIPPET1>
3+
open System.IO
4+
open System.Text
5+
6+
try
7+
// Create a file and write data to it.
8+
9+
// Create an array of bytes.
10+
let messageByte = Encoding.ASCII.GetBytes "Here is some data."
11+
12+
// Create a file using the FileStream class.
13+
let fWrite =
14+
new FileStream("test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 8, FileOptions.None)
15+
16+
// Write the number of bytes to the file.
17+
byte messageByte.Length |> fWrite.WriteByte
18+
19+
// Write the bytes to the file.
20+
fWrite.Write(messageByte, 0, messageByte.Length)
21+
22+
// Close the stream.
23+
fWrite.Close()
24+
25+
// Open a file and read the number of bytes.
26+
27+
let fRead = new FileStream("test.txt", FileMode.Open)
28+
29+
// The first byte is the string length.
30+
let length = fRead.ReadByte() |> int
31+
32+
// Create a new byte array for the data.
33+
let readBytes = Array.zeroCreate length
34+
35+
// Read the data from the file.
36+
fRead.Read(readBytes, 0, readBytes.Length) |> ignore
37+
38+
// Close the stream.
39+
fRead.Close()
40+
41+
// Display the data.
42+
printfn $"{Encoding.ASCII.GetString readBytes}"
43+
44+
printfn "Done writing and reading data."
45+
46+
with e ->
47+
printfn $"{e}"
48+
//</SNIPPET1>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net7.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="source.fs" />
9+
<Compile Include="fstreamlock.fs" />
10+
<Compile Include="source1.fs" />
11+
<Compile Include="example.fs" />
12+
</ItemGroup>
13+
</Project>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
module fstreamlock
2+
// <Snippet1>
3+
open System
4+
open System.IO
5+
open System.Text
6+
7+
let uniEncoding = UnicodeEncoding()
8+
let lastRecordText = "The last processed record number was: "
9+
let textLength = uniEncoding.GetByteCount lastRecordText
10+
let mutable recordNumber = 13
11+
let byteCount = string recordNumber |> uniEncoding.GetByteCount
12+
13+
do
14+
// <Snippet2>
15+
use fileStream =
16+
new FileStream("Test#@@#.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)
17+
// </Snippet2>
18+
19+
// <Snippet3>
20+
// Write the original file data.
21+
if fileStream.Length = 0 then
22+
let tempString = lastRecordText + string recordNumber
23+
fileStream.Write(uniEncoding.GetBytes tempString, 0, uniEncoding.GetByteCount tempString)
24+
25+
// </Snippet3>
26+
27+
// Allow the user to choose the operation.
28+
let mutable consoleInput = 'R'
29+
let readText = int fileStream.Length |> Array.zeroCreate
30+
31+
while consoleInput <> 'X' do
32+
printf "\nEnter 'R' to read, 'W' to write, 'L' to lock, 'U' to unlock, anything else to exit: "
33+
34+
let mutable tempString = stdin.ReadLine()
35+
36+
if tempString.Length = 0 then
37+
consoleInput <- 'X'
38+
else
39+
consoleInput <- Char.ToUpper tempString[0]
40+
41+
match consoleInput with
42+
| 'R' ->
43+
// Read data from the file and
44+
// write it to the console.
45+
try
46+
fileStream.Seek(0, SeekOrigin.Begin) |> ignore
47+
fileStream.Read(readText, 0, int fileStream.Length) |> ignore
48+
tempString <- String(uniEncoding.GetChars readText, 0, readText.Length)
49+
printfn $"{tempString}"
50+
recordNumber <- tempString.IndexOf ':' + 2 |> tempString.Substring |> Int32.Parse
51+
52+
// Catch the IOException generated if the
53+
// specified part of the file is locked.
54+
with :? IOException as e ->
55+
56+
printfn
57+
$"{e.GetType().Name}: The read operation could not be performed because the specified part of the file is locked."
58+
59+
// <Snippet4>
60+
| 'W' ->
61+
// Update the file.
62+
try
63+
64+
fileStream.Seek(textLength, SeekOrigin.Begin) |> ignore
65+
fileStream.Read(readText, textLength - 1, byteCount) |> ignore
66+
tempString <- String(uniEncoding.GetChars readText, textLength - 1, byteCount)
67+
recordNumber <- Int32.Parse tempString + 1
68+
fileStream.Seek(textLength, SeekOrigin.Begin) |> ignore
69+
fileStream.Write(string recordNumber |> uniEncoding.GetBytes, 0, byteCount)
70+
fileStream.Flush()
71+
printfn "Record has been updated."
72+
// </Snippet4>
73+
74+
// <Snippet6>
75+
// Catch the IOException generated if the
76+
// specified part of the file is locked.
77+
with :? IOException as e ->
78+
printfn
79+
$"{e.GetType().Name}: The write operation could not be performed because the specified part of the file is locked."
80+
// </Snippet6>
81+
82+
// Lock the specified part of the file.
83+
| 'L' ->
84+
try
85+
fileStream.Lock(textLength - 1 |> int64, byteCount)
86+
printfn "The specified part of file has been locked."
87+
with :? IOException as e ->
88+
printfn $"{e.GetType().Name}: The specified part of file is already locked."
89+
90+
// <Snippet5>
91+
// Unlock the specified part of the file.
92+
| 'U' ->
93+
try
94+
fileStream.Unlock(textLength - 1 |> int64, byteCount)
95+
printfn "The specified part of file has been unlocked."
96+
97+
with :? IOException as e ->
98+
printfn $"{e.GetType().Name}: The specified part of file is not locked by the current process."
99+
// </Snippet5>
100+
101+
// Exit the program.
102+
| _ -> consoleInput <- 'X'
103+
// </Snippet1>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module source
2+
// <Snippet1>
3+
open System
4+
open System.IO
5+
6+
7+
let fileName = "Test#@@#.dat"
8+
9+
// Create random data to write to the file.
10+
let dataArray = Array.zeroCreate 100000
11+
Random.Shared.NextBytes dataArray
12+
13+
do
14+
use fileStream = new FileStream(fileName, FileMode.Create)
15+
// Write the data to the file, byte by byte.
16+
for i = 0 to dataArray.Length - 1 do
17+
fileStream.WriteByte dataArray[i]
18+
19+
// Set the stream position to the beginning of the file.
20+
fileStream.Seek(0, SeekOrigin.Begin) |> ignore
21+
22+
// Read and verify the data.
23+
for i in 0L .. fileStream.Length - 1L do
24+
if dataArray[int i] <> (fileStream.ReadByte() |> byte) then
25+
printfn "Error writing data."
26+
exit 1
27+
28+
printfn $"The data was written to {fileStream.Name} and verified."
29+
// </Snippet1>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
module source1
2+
// <Snippet1>
3+
open System
4+
open System.IO
5+
open System.Threading
6+
7+
// Maintain state information to be passed to
8+
// EndWriteCallback and EndReadCallback.
9+
type State(fStream: FileStream, writeArray: byte[], manualEvent: ManualResetEvent) =
10+
// readArray stores data that is read from the file.
11+
let readArray = Array.zeroCreate writeArray.Length
12+
13+
member _.FStream = fStream
14+
member _.WriteArray = writeArray
15+
member _.ReadArray = readArray
16+
member _.ManualEvent = manualEvent
17+
18+
// When BeginRead is finished reading data from the file, the
19+
// EndReadCallback method is called to end the asynchronous
20+
// read operation and then verify the data.
21+
// <Snippet4>
22+
let endReadCallback (asyncResult: IAsyncResult) =
23+
let tempState = asyncResult.AsyncState :?> State
24+
let readCount = tempState.FStream.EndRead asyncResult
25+
26+
let mutable i = 0
27+
let mutable errored = false
28+
29+
while i < readCount do
30+
if tempState.ReadArray[i] <> tempState.WriteArray[i] then
31+
printfn "Error writing data."
32+
tempState.FStream.Close()
33+
errored <- true
34+
i <- readCount
35+
36+
i <- i + 1
37+
38+
printfn $"The data was written to {tempState.FStream.Name} and verified."
39+
tempState.FStream.Close()
40+
// Signal the main thread that the verification is finished.
41+
tempState.ManualEvent.Set() |> ignore
42+
// </Snippet4>
43+
44+
45+
// When BeginWrite is finished writing data to the file, the
46+
// EndWriteCallback method is called to end the asynchronous
47+
// write operation and then read back and verify the data.
48+
// <Snippet3>
49+
let endWriteCallback (asyncResult: IAsyncResult) =
50+
let tempState = asyncResult.AsyncState :?> State
51+
let fStream = tempState.FStream
52+
fStream.EndWrite asyncResult
53+
54+
// Asynchronously read back the written data.
55+
fStream.Position <- 0
56+
57+
let asyncResult =
58+
fStream.BeginRead(tempState.ReadArray, 0, tempState.ReadArray.Length, AsyncCallback endReadCallback, tempState)
59+
60+
// Concurrently do other work, such as
61+
// logging the write operation.
62+
()
63+
64+
// </Snippet3>
65+
66+
// <Snippet2>
67+
// Create a synchronization object that gets
68+
// signaled when verification is complete.
69+
let manualEvent = new ManualResetEvent false
70+
71+
// Create random data to write to the file.
72+
let writeArray = Array.zeroCreate 100000
73+
Random.Shared.NextBytes writeArray
74+
75+
let fStream =
76+
new FileStream("Test#@@#.dat", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true)
77+
78+
// Check that the FileStream was opened asynchronously.
79+
80+
if fStream.IsAsync then "" else "not "
81+
|> printfn "fStream was %sopened asynchronously."
82+
83+
// Asynchronously write to the file.
84+
let asyncResult =
85+
fStream.BeginWrite(
86+
writeArray,
87+
0,
88+
writeArray.Length,
89+
AsyncCallback endWriteCallback,
90+
State(fStream, writeArray, manualEvent)
91+
)
92+
93+
// Concurrently do other work and then wait
94+
// for the data to be written and verified.
95+
manualEvent.WaitOne(5000, false) |> ignore
96+
// </Snippet2>
97+
// </Snippet1>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net7.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="source.fs" />
9+
</ItemGroup>
10+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module source
2+
// <Snippet1>
3+
open System.IO
4+
5+
let fs = new FileStream("MyFile.txt", FileMode.OpenOrCreate, FileAccess.Read)
6+
7+
if fs.CanRead && fs.CanWrite then
8+
printfn "MyFile.txt can be both written to and read from."
9+
else if fs.CanRead then
10+
printfn "MyFile.txt is not writable."
11+
// </Snippet1>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net7.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="fstream canseek.fs" />
9+
</ItemGroup>
10+
</Project>

0 commit comments

Comments
 (0)