Skip to content

Commit 5ee65f8

Browse files
authored
System.IO.Compression F# snippets (dotnet#9065)
* DeflateStream * GZipStream * ZipArchive * ZipFile
1 parent 05036c1 commit 5ee65f8

File tree

20 files changed

+345
-0
lines changed

20 files changed

+345
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//<snippet1>
2+
module MemoryWriteReadExample
3+
4+
open System.IO
5+
open System.IO.Compression
6+
open System.Text
7+
8+
let message =
9+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
10+
11+
let s_messageBytes = Encoding.ASCII.GetBytes message
12+
13+
let compressBytesToStream stream =
14+
use compressor = new DeflateStream(stream, CompressionMode.Compress, true)
15+
compressor.Write(s_messageBytes, 0, s_messageBytes.Length)
16+
17+
let decompressStreamToBytes (stream: Stream) =
18+
stream.Position <- 0
19+
let bufferSize = 512
20+
let decompressedBytes = Array.zeroCreate bufferSize
21+
use decompressor = new DeflateStream(stream, CompressionMode.Decompress)
22+
decompressor.Read(decompressedBytes, 0, bufferSize)
23+
24+
[<EntryPoint>]
25+
let main _ =
26+
printfn $"The original string length is {s_messageBytes.Length} bytes."
27+
use stream = new MemoryStream()
28+
compressBytesToStream stream
29+
printfn $"The compressed stream length is {stream.Length} bytes."
30+
let decompressedLength = decompressStreamToBytes stream
31+
printfn $"The decompressed string length is {decompressedLength} bytes, same as the original length."
32+
0
33+
34+
// Output:
35+
// The original string length is 445 bytes.
36+
// The compressed stream length is 265 bytes.
37+
// The decompressed string length is 445 bytes, same as the original length.
38+
//</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="MemoryWriteReadExample.fs" />
9+
</ItemGroup>
10+
</Project>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
module FileCompressionModeExample
2+
//<snippet1>
3+
open System.IO
4+
open System.IO.Compression
5+
6+
let message =
7+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
8+
9+
let OriginalFileName = "original.txt"
10+
let CompressedFileName = "compressed.gz"
11+
let DecompressedFileName = "decompressed.txt"
12+
13+
let createFileToCompress () =
14+
File.WriteAllText(OriginalFileName, message)
15+
16+
let compressFile () =
17+
use originalFileStream = File.Open(OriginalFileName, FileMode.Open)
18+
use compressedFileStream = File.Create CompressedFileName
19+
use compressor = new GZipStream(compressedFileStream, CompressionMode.Compress)
20+
originalFileStream.CopyTo compressor
21+
22+
let decompressFile () =
23+
use compressedFileStream = File.Open(CompressedFileName, FileMode.Open)
24+
use outputFileStream = File.Create DecompressedFileName
25+
use decompressor = new GZipStream(compressedFileStream, CompressionMode.Decompress)
26+
decompressor.CopyTo outputFileStream
27+
28+
let printResults () =
29+
let originalSize = FileInfo(OriginalFileName).Length
30+
let compressedSize = FileInfo(CompressedFileName).Length
31+
let decompressedSize = FileInfo(DecompressedFileName).Length
32+
33+
printfn
34+
$"The original file '{OriginalFileName}' weighs {originalSize} bytes. Contents: \"{File.ReadAllText OriginalFileName}\""
35+
36+
printfn $"The compressed file '{CompressedFileName}' weighs {compressedSize} bytes."
37+
38+
printfn
39+
$"The decompressed file '{DecompressedFileName}' weighs {decompressedSize} bytes. Contents: \"{File.ReadAllText DecompressedFileName}\""
40+
41+
let deleteFiles () =
42+
File.Delete OriginalFileName
43+
File.Delete CompressedFileName
44+
File.Delete DecompressedFileName
45+
46+
createFileToCompress ()
47+
compressFile ()
48+
decompressFile ()
49+
printResults ()
50+
deleteFiles ()
51+
52+
// Output:
53+
// The original file 'original.txt' weighs 445 bytes. Contents: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
54+
//
55+
// The compressed file 'compressed.gz' weighs 283 bytes.
56+
//
57+
// The decompressed file 'decompressed.txt' weighs 445 bytes. Contents: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
58+
//</snippet1>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module MemoryWriteReadExample
2+
//<snippet1>
3+
open System.IO
4+
open System.IO.Compression
5+
open System.Text
6+
7+
let message =
8+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
9+
10+
let s_messageBytes = Encoding.ASCII.GetBytes message
11+
12+
let compressBytesToStream stream =
13+
use compressor =
14+
new GZipStream(stream, CompressionLevel.SmallestSize, leaveOpen = true)
15+
16+
compressor.Write(s_messageBytes, 0, s_messageBytes.Length)
17+
18+
let decompressStreamToBytes (stream: Stream) =
19+
stream.Position <- 0
20+
let bufferSize = 512
21+
let decompressedBytes = Array.zeroCreate bufferSize
22+
use decompressor = new GZipStream(stream, CompressionMode.Decompress)
23+
decompressor.Read(decompressedBytes, 0, bufferSize)
24+
25+
[<EntryPoint>]
26+
let main _ =
27+
printfn $"The original string length is {s_messageBytes.Length} bytes."
28+
use stream = new MemoryStream()
29+
compressBytesToStream stream
30+
printfn $"The compressed stream length is {stream.Length} bytes."
31+
let decompressedLength = decompressStreamToBytes stream
32+
printfn $"The decompressed string length is {decompressedLength} bytes, same as the original length."
33+
0
34+
35+
// Output:
36+
// The original string length is 445 bytes.
37+
// The compressed stream length is 282 bytes.
38+
// The decompressed string length is 445 bytes, same as the original length.
39+
//</snippet1>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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="FileCompressionModeExample.fs" />
9+
<Compile Include="MemoryWriteReadExample.fs" />
10+
</ItemGroup>
11+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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="program1.fs" />
9+
<Compile Include="program2.fs" />
10+
</ItemGroup>
11+
</Project>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module program1
2+
3+
// <snippet1>
4+
open System.IO
5+
open System.IO.Compression
6+
7+
do
8+
use zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open)
9+
10+
use archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update)
11+
12+
let readmeEntry = archive.CreateEntry "Readme.txt"
13+
use writer = new StreamWriter(readmeEntry.Open())
14+
15+
writer.WriteLine "Information about this package."
16+
writer.WriteLine "========================"
17+
// </snippet1>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module program2
2+
3+
// <snippet2>
4+
open System.IO
5+
open System.IO.Compression
6+
7+
do
8+
use zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open)
9+
10+
use archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update)
11+
12+
let readmeEntry = archive.CreateEntry("Readme.txt", CompressionLevel.Optimal)
13+
use writer = new StreamWriter(readmeEntry.Open())
14+
15+
writer.WriteLine "Information about this package."
16+
writer.WriteLine "========================"
17+
// </snippet2>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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="program3.fs" />
9+
<Compile Include="program1.fs" />
10+
</ItemGroup>
11+
</Project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module program1
2+
// <snippet1>
3+
open System
4+
open System.IO;
5+
open System.IO.Compression;
6+
7+
[<EntryPoint>]
8+
let main _ =
9+
let zipPath = @".\result.zip"
10+
11+
printfn "Provide path where to extract the zip file:"
12+
let extractPath = stdin.ReadLine();
13+
14+
// Normalizes the path.
15+
let mutable extractPath = Path.GetFullPath extractPath
16+
17+
// Ensures that the last character on the extraction path
18+
// is the directory separator char.
19+
// Without this, a malicious zip file could try to traverse outside of the expected
20+
// extraction path.
21+
if extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) |> not then
22+
extractPath <- extractPath + string Path.DirectorySeparatorChar
23+
24+
use archive = ZipFile.OpenRead zipPath
25+
26+
for entry in archive.Entries do
27+
if entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) then
28+
// Gets the full path to ensure that relative segments are removed.
29+
let destinationPath = Path.GetFullPath(Path.Combine(extractPath, entry.FullName))
30+
31+
// Ordinal match is safest, case-sensitive volumes can be mounted within volumes that
32+
// are case-insensitive.
33+
if destinationPath.StartsWith(extractPath, StringComparison.Ordinal) then
34+
entry.ExtractToFile destinationPath
35+
0
36+
37+
// </snippet1>

0 commit comments

Comments
 (0)