mirror of
https://github.com/markjprice/cs11dotnet7.git
synced 2026-01-07 00:29:58 +01:00
Initial commit
This commit is contained in:
parent
17ad36d6ad
commit
3d241b2154
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
14
vs4win/Chapter09/Ch09Ex02SerializingShapes/Circle.cs
Normal file
14
vs4win/Chapter09/Ch09Ex02SerializingShapes/Circle.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
namespace Packt.Shared;
|
||||
|
||||
public class Circle : Shape
|
||||
{
|
||||
public override double Area
|
||||
{
|
||||
get
|
||||
{
|
||||
return Math.PI * Radius * Radius;
|
||||
}
|
||||
}
|
||||
|
||||
public double Radius { get; set; }
|
||||
}
|
||||
50
vs4win/Chapter09/Ch09Ex02SerializingShapes/Program.cs
Normal file
50
vs4win/Chapter09/Ch09Ex02SerializingShapes/Program.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using Packt.Shared; // Circle, Rectangle, Shape
|
||||
using System.Xml.Serialization; // XmlSerializer
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
// create a file path to write to
|
||||
string path = Combine(CurrentDirectory, "shapes.xml");
|
||||
|
||||
// create a list of Shape objects to serialize
|
||||
List<Shape> listOfShapes = new()
|
||||
{
|
||||
new Circle { Colour = "Red", Radius = 2.5 },
|
||||
new Rectangle { Colour = "Blue", Height = 20.0, Width = 10.0 },
|
||||
new Circle { Colour = "Green", Radius = 8 },
|
||||
new Circle { Colour = "Purple", Radius = 12.3 },
|
||||
new Rectangle { Colour = "Blue", Height = 45.0, Width = 18.0 }
|
||||
};
|
||||
|
||||
// create an object that knows how to serialize and deserialize
|
||||
// a list of Shape objects
|
||||
XmlSerializer serializerXml = new(listOfShapes.GetType());
|
||||
|
||||
WriteLine("Saving shapes to XML file:");
|
||||
|
||||
using (FileStream fileXml = File.Create(path))
|
||||
{
|
||||
serializerXml.Serialize(fileXml, listOfShapes);
|
||||
}
|
||||
|
||||
WriteLine("Loading shapes from XML file:");
|
||||
List<Shape>? loadedShapesXml = null;
|
||||
|
||||
using (FileStream fileXml = File.Open(path, FileMode.Open))
|
||||
{
|
||||
loadedShapesXml =
|
||||
serializerXml.Deserialize(fileXml) as List<Shape>;
|
||||
}
|
||||
|
||||
if (loadedShapesXml == null)
|
||||
{
|
||||
WriteLine($"{nameof(loadedShapesXml)} is empty.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Shape item in loadedShapesXml)
|
||||
{
|
||||
WriteLine($"{item.GetType().Name} is {item.Colour} and has an area of {item.Area:N2}");
|
||||
}
|
||||
}
|
||||
15
vs4win/Chapter09/Ch09Ex02SerializingShapes/Rectangle.cs
Normal file
15
vs4win/Chapter09/Ch09Ex02SerializingShapes/Rectangle.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
namespace Packt.Shared;
|
||||
|
||||
public class Rectangle : Shape
|
||||
{
|
||||
public override double Area
|
||||
{
|
||||
get
|
||||
{
|
||||
return Height * Width;
|
||||
}
|
||||
}
|
||||
|
||||
public double Height { get; set; }
|
||||
public double Width { get; set; }
|
||||
}
|
||||
11
vs4win/Chapter09/Ch09Ex02SerializingShapes/Shape.cs
Normal file
11
vs4win/Chapter09/Ch09Ex02SerializingShapes/Shape.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System.Xml.Serialization;
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
[XmlInclude(typeof(Circle))]
|
||||
[XmlInclude(typeof(Rectangle))]
|
||||
public abstract class Shape
|
||||
{
|
||||
public string? Colour { get; set; }
|
||||
public abstract double Area { get; }
|
||||
}
|
||||
55
vs4win/Chapter09/Chapter09.sln
Normal file
55
vs4win/Chapter09/Chapter09.sln
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32210.308
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkingWithFileSystems", "WorkingWithFileSystems\WorkingWithFileSystems.csproj", "{FCC1830B-5341-4ED6-B9B3-1885B1724D6E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkingWithStreams", "WorkingWithStreams\WorkingWithStreams.csproj", "{3D9CAC15-E6F2-462E-9821-45BEF1A76326}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkingWithEncodings", "WorkingWithEncodings\WorkingWithEncodings.csproj", "{70A9750E-5C55-4879-B601-20AC5F6CDCB4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithSerialization", "WorkingWithSerialization\WorkingWithSerialization.csproj", "{7493AA42-910F-4FB2-B3D4-34553255BD54}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithJson", "WorkingWithJson\WorkingWithJson.csproj", "{CA13AF96-7EE4-42C4-A671-C373E218726A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch09Ex02SerializingShapes", "Ch09Ex02SerializingShapes\Ch09Ex02SerializingShapes.csproj", "{27FA94CC-1856-4512-9D09-0214CF846311}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FCC1830B-5341-4ED6-B9B3-1885B1724D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FCC1830B-5341-4ED6-B9B3-1885B1724D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FCC1830B-5341-4ED6-B9B3-1885B1724D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FCC1830B-5341-4ED6-B9B3-1885B1724D6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3D9CAC15-E6F2-462E-9821-45BEF1A76326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3D9CAC15-E6F2-462E-9821-45BEF1A76326}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3D9CAC15-E6F2-462E-9821-45BEF1A76326}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3D9CAC15-E6F2-462E-9821-45BEF1A76326}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{70A9750E-5C55-4879-B601-20AC5F6CDCB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70A9750E-5C55-4879-B601-20AC5F6CDCB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70A9750E-5C55-4879-B601-20AC5F6CDCB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70A9750E-5C55-4879-B601-20AC5F6CDCB4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7493AA42-910F-4FB2-B3D4-34553255BD54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7493AA42-910F-4FB2-B3D4-34553255BD54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7493AA42-910F-4FB2-B3D4-34553255BD54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7493AA42-910F-4FB2-B3D4-34553255BD54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA13AF96-7EE4-42C4-A671-C373E218726A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA13AF96-7EE4-42C4-A671-C373E218726A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA13AF96-7EE4-42C4-A671-C373E218726A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA13AF96-7EE4-42C4-A671-C373E218726A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{27FA94CC-1856-4512-9D09-0214CF846311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{27FA94CC-1856-4512-9D09-0214CF846311}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{27FA94CC-1856-4512-9D09-0214CF846311}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{27FA94CC-1856-4512-9D09-0214CF846311}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {285FD445-B8EB-4756-9152-F155A7861DD8}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
51
vs4win/Chapter09/WorkingWithEncodings/Program.cs
Normal file
51
vs4win/Chapter09/WorkingWithEncodings/Program.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using Packt.Shared;
|
||||
using System.Text;
|
||||
|
||||
WriteLine("Encodings");
|
||||
WriteLine("[1] ASCII");
|
||||
WriteLine("[2] UTF-7");
|
||||
WriteLine("[3] UTF-8");
|
||||
WriteLine("[4] UTF-16 (Unicode)");
|
||||
WriteLine("[5] UTF-32");
|
||||
WriteLine("[6] Latin1");
|
||||
WriteLine("[any other key] Default encoding");
|
||||
WriteLine();
|
||||
|
||||
// choose an encoding
|
||||
Write("Press a number to choose an encoding.");
|
||||
ConsoleKey number = ReadKey(intercept: true).Key;
|
||||
WriteLine(); WriteLine();
|
||||
|
||||
Encoding encoder = number switch
|
||||
{
|
||||
ConsoleKey.D1 or ConsoleKey.NumPad1 => Encoding.ASCII,
|
||||
ConsoleKey.D2 or ConsoleKey.NumPad2 => Encoding.UTF7,
|
||||
ConsoleKey.D3 or ConsoleKey.NumPad3 => Encoding.UTF8,
|
||||
ConsoleKey.D4 or ConsoleKey.NumPad4 => Encoding.Unicode,
|
||||
ConsoleKey.D5 or ConsoleKey.NumPad5 => Encoding.UTF32,
|
||||
ConsoleKey.D6 or ConsoleKey.NumPad6 => Encoding.Latin1,
|
||||
_ => Encoding.Default
|
||||
};
|
||||
|
||||
// define a string to encode
|
||||
string message = "Café £4.39";
|
||||
WriteLine($"Text to encode: {message} Characters: {message.Length}");
|
||||
|
||||
// encode the string into a byte array
|
||||
byte[] encoded = encoder.GetBytes(message);
|
||||
|
||||
// check how many bytes the encoding needed
|
||||
WriteLine("{0} used {1:N0} bytes.",
|
||||
encoder.GetType().Name, encoded.Length);
|
||||
WriteLine();
|
||||
|
||||
// enumerate each byte
|
||||
WriteLine($"BYTE | HEX | CHAR");
|
||||
foreach (byte b in encoded)
|
||||
{
|
||||
WriteLine($"{b,4} | {b.ToString("X"),3} | {(char)b,4}");
|
||||
}
|
||||
|
||||
// decode the byte array back into a string and display it
|
||||
string decoded = encoder.GetString(encoded);
|
||||
WriteLine(decoded);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
12
vs4win/Chapter09/WorkingWithFileSystems/Program.Helpers.cs
Normal file
12
vs4win/Chapter09/WorkingWithFileSystems/Program.Helpers.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
partial class Program
|
||||
{
|
||||
static void SectionTitle(string title)
|
||||
{
|
||||
ConsoleColor previousColor = ForegroundColor;
|
||||
ForegroundColor = ConsoleColor.Yellow;
|
||||
WriteLine("*");
|
||||
WriteLine($"* {title}");
|
||||
WriteLine("*");
|
||||
ForegroundColor = previousColor;
|
||||
}
|
||||
}
|
||||
132
vs4win/Chapter09/WorkingWithFileSystems/Program.cs
Normal file
132
vs4win/Chapter09/WorkingWithFileSystems/Program.cs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
using static System.IO.Directory;
|
||||
using static System.IO.Path;
|
||||
using static System.Environment;
|
||||
|
||||
SectionTitle("Handling cross-platform environments and filesystems");
|
||||
|
||||
WriteLine("{0,-33} {1}", arg0: "Path.PathSeparator",
|
||||
arg1: PathSeparator);
|
||||
WriteLine("{0,-33} {1}", arg0: "Path.DirectorySeparatorChar",
|
||||
arg1: DirectorySeparatorChar);
|
||||
WriteLine("{0,-33} {1}", arg0: "Directory.GetCurrentDirectory()",
|
||||
arg1: GetCurrentDirectory());
|
||||
WriteLine("{0,-33} {1}", arg0: "Environment.CurrentDirectory",
|
||||
arg1: CurrentDirectory);
|
||||
WriteLine("{0,-33} {1}", arg0: "Environment.SystemDirectory",
|
||||
arg1: SystemDirectory);
|
||||
WriteLine("{0,-33} {1}", arg0: "Path.GetTempPath()",
|
||||
arg1: GetTempPath());
|
||||
WriteLine("GetFolderPath(SpecialFolder");
|
||||
WriteLine("{0,-33} {1}", arg0: " .System)",
|
||||
arg1: GetFolderPath(SpecialFolder.System));
|
||||
WriteLine("{0,-33} {1}", arg0: " .ApplicationData)",
|
||||
arg1: GetFolderPath(SpecialFolder.ApplicationData));
|
||||
WriteLine("{0,-33} {1}", arg0: " .MyDocuments)",
|
||||
arg1: GetFolderPath(SpecialFolder.MyDocuments));
|
||||
WriteLine("{0,-33} {1}", arg0: " .Personal)",
|
||||
arg1: GetFolderPath(SpecialFolder.Personal));
|
||||
|
||||
SectionTitle("Managing drives");
|
||||
|
||||
WriteLine("{0,-30} | {1,-10} | {2,-7} | {3,18} | {4,18}",
|
||||
"NAME", "TYPE", "FORMAT", "SIZE (BYTES)", "FREE SPACE");
|
||||
|
||||
foreach (DriveInfo drive in DriveInfo.GetDrives())
|
||||
{
|
||||
if (drive.IsReady)
|
||||
{
|
||||
WriteLine(
|
||||
"{0,-30} | {1,-10} | {2,-7} | {3,18:N0} | {4,18:N0}",
|
||||
drive.Name, drive.DriveType, drive.DriveFormat,
|
||||
drive.TotalSize, drive.AvailableFreeSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine("{0,-30} | {1,-10}", drive.Name, drive.DriveType);
|
||||
}
|
||||
}
|
||||
|
||||
SectionTitle("Managing directories");
|
||||
|
||||
// define a directory path for a new folder
|
||||
// starting in the user's folder
|
||||
string newFolder = Combine(
|
||||
GetFolderPath(SpecialFolder.Personal), "NewFolder");
|
||||
|
||||
WriteLine($"Working with: {newFolder}");
|
||||
|
||||
// check if it exists
|
||||
WriteLine($"Does it exist? {Exists(newFolder)}");
|
||||
|
||||
// create directory
|
||||
WriteLine("Creating it...");
|
||||
CreateDirectory(newFolder);
|
||||
WriteLine($"Does it exist? {Exists(newFolder)}");
|
||||
Write("Confirm the directory exists, and then press ENTER: ");
|
||||
ReadLine();
|
||||
|
||||
// delete directory
|
||||
WriteLine("Deleting it...");
|
||||
Delete(newFolder, recursive: true);
|
||||
WriteLine($"Does it exist? {Exists(newFolder)}");
|
||||
|
||||
SectionTitle("Managing files");
|
||||
|
||||
// define a directory path to output files
|
||||
// starting in the user's folder
|
||||
string dir = Combine(
|
||||
GetFolderPath(SpecialFolder.Personal), "OutputFiles");
|
||||
|
||||
CreateDirectory(dir);
|
||||
|
||||
// define file paths
|
||||
string textFile = Combine(dir, "Dummy.txt");
|
||||
string backupFile = Combine(dir, "Dummy.bak");
|
||||
WriteLine($"Working with: {textFile}");
|
||||
|
||||
// check if a file exists
|
||||
WriteLine($"Does it exist? {File.Exists(textFile)}");
|
||||
|
||||
// create a new text file and write a line to it
|
||||
StreamWriter textWriter = File.CreateText(textFile);
|
||||
textWriter.WriteLine("Hello, C#!");
|
||||
textWriter.Close(); // close file and release resources
|
||||
WriteLine($"Does it exist? {File.Exists(textFile)}");
|
||||
|
||||
// copy the file, and overwrite if it already exists
|
||||
File.Copy(sourceFileName: textFile,
|
||||
destFileName: backupFile, overwrite: true);
|
||||
|
||||
WriteLine(
|
||||
$"Does {backupFile} exist? {File.Exists(backupFile)}");
|
||||
|
||||
Write("Confirm the files exist, and then press ENTER: ");
|
||||
ReadLine();
|
||||
|
||||
// delete file
|
||||
File.Delete(textFile);
|
||||
WriteLine($"Does it exist? {File.Exists(textFile)}");
|
||||
|
||||
// read from the text file backup
|
||||
WriteLine($"Reading contents of {backupFile}:");
|
||||
StreamReader textReader = File.OpenText(backupFile);
|
||||
WriteLine(textReader.ReadToEnd());
|
||||
textReader.Close();
|
||||
|
||||
SectionTitle("Managing paths");
|
||||
|
||||
WriteLine($"Folder Name: {GetDirectoryName(textFile)}");
|
||||
WriteLine($"File Name: {GetFileName(textFile)}");
|
||||
WriteLine("File Name without Extension: {0}",
|
||||
GetFileNameWithoutExtension(textFile));
|
||||
WriteLine($"File Extension: {GetExtension(textFile)}");
|
||||
WriteLine($"Random File Name: {GetRandomFileName()}");
|
||||
WriteLine($"Temporary File Name: {GetTempFileName()}");
|
||||
|
||||
SectionTitle("Getting file information ");
|
||||
|
||||
FileInfo info = new(backupFile);
|
||||
WriteLine($"{backupFile}:");
|
||||
WriteLine($"Contains {info.Length} bytes");
|
||||
WriteLine($"Last accessed {info.LastAccessTime}");
|
||||
WriteLine($"Has readonly set to {info.IsReadOnly}");
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
23
vs4win/Chapter09/WorkingWithJson/Book.cs
Normal file
23
vs4win/Chapter09/WorkingWithJson/Book.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using System.Text.Json.Serialization; // [JsonInclude]
|
||||
|
||||
public class Book
|
||||
{
|
||||
// constructor to set non-nullable property
|
||||
public Book(string title)
|
||||
{
|
||||
Title = title;
|
||||
}
|
||||
|
||||
// properties
|
||||
public string Title { get; set; }
|
||||
public string? Author { get; set; }
|
||||
|
||||
// fields
|
||||
[JsonInclude] // include this field
|
||||
public DateTime PublishDate;
|
||||
|
||||
[JsonInclude] // include this field
|
||||
public DateTimeOffset Created;
|
||||
|
||||
public ushort Pages;
|
||||
}
|
||||
39
vs4win/Chapter09/WorkingWithJson/Program.cs
Normal file
39
vs4win/Chapter09/WorkingWithJson/Program.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using System.Text.Json; // JsonSerializer
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
Book mybook = new(title:
|
||||
"C# 11 and .NET 7 - Modern Cross-platform Development")
|
||||
{
|
||||
Author = "Mark J Price",
|
||||
PublishDate = new(year: 2022, month: 11, day: 8),
|
||||
Pages = 823,
|
||||
Created = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
JsonSerializerOptions options = new()
|
||||
{
|
||||
/*
|
||||
IncludeFields = true, // includes all fields
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
*/
|
||||
};
|
||||
|
||||
string filePath = Combine(CurrentDirectory, "mybook.json");
|
||||
|
||||
using (Stream fileStream = File.Create(filePath))
|
||||
{
|
||||
JsonSerializer.Serialize<Book>(
|
||||
utf8Json: fileStream, value: mybook, options);
|
||||
}
|
||||
|
||||
WriteLine("Written {0:N0} bytes of JSON to {1}",
|
||||
arg0: new FileInfo(filePath).Length,
|
||||
arg1: filePath);
|
||||
WriteLine();
|
||||
|
||||
// Display the serialized object graph
|
||||
WriteLine(File.ReadAllText(filePath));
|
||||
14
vs4win/Chapter09/WorkingWithJson/WorkingWithJson.csproj
Normal file
14
vs4win/Chapter09/WorkingWithJson/WorkingWithJson.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
26
vs4win/Chapter09/WorkingWithSerialization/Person.cs
Normal file
26
vs4win/Chapter09/WorkingWithSerialization/Person.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using System.Xml.Serialization; // [XmlAttribute]
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
public class Person
|
||||
{
|
||||
public Person() { }
|
||||
|
||||
public Person(decimal initialSalary)
|
||||
{
|
||||
Salary = initialSalary;
|
||||
}
|
||||
|
||||
[XmlAttribute("fname")]
|
||||
public string? FirstName { get; set; }
|
||||
|
||||
[XmlAttribute("lname")]
|
||||
public string? LastName { get; set; }
|
||||
|
||||
[XmlAttribute("dob")]
|
||||
public DateTime DateOfBirth { get; set; }
|
||||
|
||||
public HashSet<Person>? Children { get; set; }
|
||||
|
||||
protected decimal Salary { get; set; }
|
||||
}
|
||||
117
vs4win/Chapter09/WorkingWithSerialization/Program.cs
Normal file
117
vs4win/Chapter09/WorkingWithSerialization/Program.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
using System.Xml.Serialization; // XmlSerializer
|
||||
using Packt.Shared; // Person
|
||||
using NewJson = System.Text.Json.JsonSerializer;
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
// create an object graph
|
||||
List<Person> people = new()
|
||||
{
|
||||
new(30000M)
|
||||
{
|
||||
FirstName = "Alice",
|
||||
LastName = "Smith",
|
||||
DateOfBirth = new(year: 1974, month: 3, day: 14)
|
||||
},
|
||||
new(40000M)
|
||||
{
|
||||
FirstName = "Bob",
|
||||
LastName = "Jones",
|
||||
DateOfBirth = new(year: 1969, month: 11, day: 23)
|
||||
},
|
||||
new(20000M)
|
||||
{
|
||||
FirstName = "Charlie",
|
||||
LastName = "Cox",
|
||||
DateOfBirth = new(year: 1984, month: 5, day: 4),
|
||||
Children = new()
|
||||
{
|
||||
new(0M)
|
||||
{
|
||||
FirstName = "Sally",
|
||||
LastName = "Cox",
|
||||
DateOfBirth = new(year: 2012, month: 7, day: 12)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// create object that will format a List of Persons as XML
|
||||
XmlSerializer xs = new(type: people.GetType());
|
||||
|
||||
// create a file to write to
|
||||
string path = Combine(CurrentDirectory, "people.xml");
|
||||
|
||||
using (FileStream stream = File.Create(path))
|
||||
{
|
||||
// serialize the object graph to the stream
|
||||
xs.Serialize(stream, people);
|
||||
}
|
||||
|
||||
WriteLine("Written {0:N0} bytes of XML to {1}",
|
||||
arg0: new FileInfo(path).Length,
|
||||
arg1: path);
|
||||
WriteLine();
|
||||
|
||||
// Display the serialized object graph
|
||||
WriteLine(File.ReadAllText(path));
|
||||
|
||||
WriteLine();
|
||||
WriteLine("* Deserializing XML files");
|
||||
|
||||
using (FileStream xmlLoad = File.Open(path, FileMode.Open))
|
||||
{
|
||||
// deserialize and cast the object graph into a List of Person
|
||||
List<Person>? loadedPeople =
|
||||
xs.Deserialize(xmlLoad) as List<Person>;
|
||||
|
||||
if (loadedPeople is not null)
|
||||
{
|
||||
foreach (Person p in loadedPeople)
|
||||
{
|
||||
WriteLine("{0} has {1} children.",
|
||||
p.LastName, p.Children?.Count ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a file to write to
|
||||
string jsonPath = Combine(CurrentDirectory, "people.json");
|
||||
|
||||
using (StreamWriter jsonStream = File.CreateText(jsonPath))
|
||||
{
|
||||
// create an object that will format as JSON
|
||||
Newtonsoft.Json.JsonSerializer jss = new();
|
||||
|
||||
// serialize the object graph into a string
|
||||
jss.Serialize(jsonStream, people);
|
||||
}
|
||||
|
||||
WriteLine();
|
||||
WriteLine("Written {0:N0} bytes of JSON to: {1}",
|
||||
arg0: new FileInfo(jsonPath).Length,
|
||||
arg1: jsonPath);
|
||||
|
||||
// Display the serialized object graph
|
||||
WriteLine(File.ReadAllText(jsonPath));
|
||||
|
||||
WriteLine();
|
||||
WriteLine("* Deserializing JSON files");
|
||||
|
||||
using (FileStream jsonLoad = File.Open(jsonPath, FileMode.Open))
|
||||
{
|
||||
// deserialize object graph into a List of Person
|
||||
List<Person>? loadedPeople =
|
||||
await NewJson.DeserializeAsync(utf8Json: jsonLoad,
|
||||
returnType: typeof(List<Person>)) as List<Person>;
|
||||
|
||||
if (loadedPeople is not null)
|
||||
{
|
||||
foreach (Person p in loadedPeople)
|
||||
{
|
||||
WriteLine("{0} has {1} children.",
|
||||
p.LastName, p.Children?.Count ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
78
vs4win/Chapter09/WorkingWithStreams/Program.Compress.cs
Normal file
78
vs4win/Chapter09/WorkingWithStreams/Program.Compress.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
using System.IO.Compression; // BrotliStream, GZipStream, CompressionMode
|
||||
using System.Xml; // XmlWriter, XmlReader
|
||||
|
||||
using static System.Environment; // CurrentDirectory
|
||||
using static System.IO.Path; // Combine
|
||||
|
||||
partial class Program
|
||||
{
|
||||
static void Compress(string algorithm = "gzip")
|
||||
{
|
||||
// define a file path using algorithm as file extension
|
||||
string filePath = Combine(
|
||||
CurrentDirectory, $"streams.{algorithm}");
|
||||
|
||||
FileStream file = File.Create(filePath);
|
||||
Stream compressor;
|
||||
if (algorithm == "gzip")
|
||||
{
|
||||
compressor = new GZipStream(file, CompressionMode.Compress);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressor = new BrotliStream(file, CompressionMode.Compress);
|
||||
}
|
||||
|
||||
using (compressor)
|
||||
{
|
||||
using (XmlWriter xml = XmlWriter.Create(compressor))
|
||||
{
|
||||
xml.WriteStartDocument();
|
||||
xml.WriteStartElement("callsigns");
|
||||
foreach (string item in Viper.Callsigns)
|
||||
{
|
||||
xml.WriteElementString("callsign", item);
|
||||
}
|
||||
}
|
||||
} // also closes the underlying stream
|
||||
|
||||
// output all the contents of the compressed file
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
filePath, new FileInfo(filePath).Length);
|
||||
|
||||
WriteLine($"The compressed contents:");
|
||||
WriteLine(File.ReadAllText(filePath));
|
||||
|
||||
// read a compressed file
|
||||
WriteLine("Reading the compressed XML file:");
|
||||
file = File.Open(filePath, FileMode.Open);
|
||||
Stream decompressor;
|
||||
if (algorithm == "gzip")
|
||||
{
|
||||
decompressor = new GZipStream(
|
||||
file, CompressionMode.Decompress);
|
||||
}
|
||||
else
|
||||
{
|
||||
decompressor = new BrotliStream(
|
||||
file, CompressionMode.Decompress);
|
||||
}
|
||||
|
||||
using (decompressor)
|
||||
{
|
||||
using (XmlReader reader = XmlReader.Create(decompressor))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
// check if we are on an element node named callsign
|
||||
if ((reader.NodeType == XmlNodeType.Element)
|
||||
&& (reader.Name == "callsign"))
|
||||
{
|
||||
reader.Read(); // move to the text inside element
|
||||
WriteLine($"{reader.Value}"); // read its value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
vs4win/Chapter09/WorkingWithStreams/Program.Helpers.cs
Normal file
12
vs4win/Chapter09/WorkingWithStreams/Program.Helpers.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
partial class Program
|
||||
{
|
||||
static void SectionTitle(string title)
|
||||
{
|
||||
ConsoleColor previousColor = ForegroundColor;
|
||||
ForegroundColor = ConsoleColor.Yellow;
|
||||
WriteLine("*");
|
||||
WriteLine($"* {title}");
|
||||
WriteLine("*");
|
||||
ForegroundColor = previousColor;
|
||||
}
|
||||
}
|
||||
94
vs4win/Chapter09/WorkingWithStreams/Program.cs
Normal file
94
vs4win/Chapter09/WorkingWithStreams/Program.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
using System.Xml;
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
SectionTitle("Writing to text streams");
|
||||
|
||||
// define a file to write to
|
||||
string textFile = Combine(CurrentDirectory, "streams.txt");
|
||||
|
||||
// create a text file and return a helper writer
|
||||
StreamWriter text = File.CreateText(textFile);
|
||||
|
||||
// enumerate the strings, writing each one
|
||||
// to the stream on a separate line
|
||||
foreach (string item in Viper.Callsigns)
|
||||
{
|
||||
text.WriteLine(item);
|
||||
}
|
||||
text.Close(); // release resources
|
||||
|
||||
// output the contents of the file
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: textFile,
|
||||
arg1: new FileInfo(textFile).Length);
|
||||
|
||||
WriteLine(File.ReadAllText(textFile));
|
||||
|
||||
SectionTitle("Writing to XML streams");
|
||||
|
||||
// define a file path to write to
|
||||
string xmlFile = Combine(CurrentDirectory, "streams.xml");
|
||||
|
||||
// declare variables for the filestream and XML writer
|
||||
FileStream? xmlFileStream = null;
|
||||
XmlWriter? xml = null;
|
||||
|
||||
try
|
||||
{
|
||||
// create a file stream
|
||||
xmlFileStream = File.Create(xmlFile);
|
||||
|
||||
// wrap the file stream in an XML writer helper
|
||||
// and automatically indent nested elements
|
||||
xml = XmlWriter.Create(xmlFileStream,
|
||||
new XmlWriterSettings { Indent = true });
|
||||
|
||||
// write the XML declaration
|
||||
xml.WriteStartDocument();
|
||||
|
||||
// write a root element
|
||||
xml.WriteStartElement("callsigns");
|
||||
|
||||
// enumerate the strings writing each one to the stream
|
||||
foreach (string item in Viper.Callsigns)
|
||||
{
|
||||
xml.WriteElementString("callsign", item);
|
||||
}
|
||||
|
||||
// write the close root element
|
||||
xml.WriteEndElement();
|
||||
|
||||
// close helper and stream
|
||||
xml.Close();
|
||||
xmlFileStream.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// if the path doesn't exist the exception will be caught
|
||||
WriteLine($"{ex.GetType()} says {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (xml != null)
|
||||
{
|
||||
xml.Dispose();
|
||||
WriteLine("The XML writer's unmanaged resources have been disposed.");
|
||||
if (xmlFileStream != null)
|
||||
{
|
||||
xmlFileStream.Dispose();
|
||||
WriteLine("The file stream's unmanaged resources have been disposed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// output all the contents of the file
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: xmlFile,
|
||||
arg1: new FileInfo(xmlFile).Length);
|
||||
WriteLine(File.ReadAllText(xmlFile));
|
||||
|
||||
SectionTitle("Compressing streams");
|
||||
Compress(algorithm: "gzip");
|
||||
Compress(algorithm: "brotli");
|
||||
9
vs4win/Chapter09/WorkingWithStreams/Viper.cs
Normal file
9
vs4win/Chapter09/WorkingWithStreams/Viper.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
static class Viper
|
||||
{
|
||||
// define an array of Viper pilot call signs
|
||||
public static string[] Callsigns = new[]
|
||||
{
|
||||
"Husker", "Starbuck", "Apollo", "Boomer",
|
||||
"Bulldog", "Athena", "Helo", "Racetrack"
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
14
vscode/Chapter09/Ch09Ex02SerializingShapes/Circle.cs
Normal file
14
vscode/Chapter09/Ch09Ex02SerializingShapes/Circle.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
namespace Packt.Shared;
|
||||
|
||||
public class Circle : Shape
|
||||
{
|
||||
public override double Area
|
||||
{
|
||||
get
|
||||
{
|
||||
return Math.PI * Radius * Radius;
|
||||
}
|
||||
}
|
||||
|
||||
public double Radius { get; set; }
|
||||
}
|
||||
50
vscode/Chapter09/Ch09Ex02SerializingShapes/Program.cs
Normal file
50
vscode/Chapter09/Ch09Ex02SerializingShapes/Program.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using Packt.Shared; // Circle, Rectangle, Shape
|
||||
using System.Xml.Serialization; // XmlSerializer
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
// create a file path to write to
|
||||
string path = Combine(CurrentDirectory, "shapes.xml");
|
||||
|
||||
// create a list of Shape objects to serialize
|
||||
List<Shape> listOfShapes = new()
|
||||
{
|
||||
new Circle { Colour = "Red", Radius = 2.5 },
|
||||
new Rectangle { Colour = "Blue", Height = 20.0, Width = 10.0 },
|
||||
new Circle { Colour = "Green", Radius = 8 },
|
||||
new Circle { Colour = "Purple", Radius = 12.3 },
|
||||
new Rectangle { Colour = "Blue", Height = 45.0, Width = 18.0 }
|
||||
};
|
||||
|
||||
// create an object that knows how to serialize and deserialize
|
||||
// a list of Shape objects
|
||||
XmlSerializer serializerXml = new(listOfShapes.GetType());
|
||||
|
||||
WriteLine("Saving shapes to XML file:");
|
||||
|
||||
using (FileStream fileXml = File.Create(path))
|
||||
{
|
||||
serializerXml.Serialize(fileXml, listOfShapes);
|
||||
}
|
||||
|
||||
WriteLine("Loading shapes from XML file:");
|
||||
List<Shape>? loadedShapesXml = null;
|
||||
|
||||
using (FileStream fileXml = File.Open(path, FileMode.Open))
|
||||
{
|
||||
loadedShapesXml =
|
||||
serializerXml.Deserialize(fileXml) as List<Shape>;
|
||||
}
|
||||
|
||||
if (loadedShapesXml == null)
|
||||
{
|
||||
WriteLine($"{nameof(loadedShapesXml)} is empty.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Shape item in loadedShapesXml)
|
||||
{
|
||||
WriteLine($"{item.GetType().Name} is {item.Colour} and has an area of {item.Area:N2}");
|
||||
}
|
||||
}
|
||||
15
vscode/Chapter09/Ch09Ex02SerializingShapes/Rectangle.cs
Normal file
15
vscode/Chapter09/Ch09Ex02SerializingShapes/Rectangle.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
namespace Packt.Shared;
|
||||
|
||||
public class Rectangle : Shape
|
||||
{
|
||||
public override double Area
|
||||
{
|
||||
get
|
||||
{
|
||||
return Height * Width;
|
||||
}
|
||||
}
|
||||
|
||||
public double Height { get; set; }
|
||||
public double Width { get; set; }
|
||||
}
|
||||
11
vscode/Chapter09/Ch09Ex02SerializingShapes/Shape.cs
Normal file
11
vscode/Chapter09/Ch09Ex02SerializingShapes/Shape.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System.Xml.Serialization;
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
[XmlInclude(typeof(Circle))]
|
||||
[XmlInclude(typeof(Rectangle))]
|
||||
public abstract class Shape
|
||||
{
|
||||
public string? Colour { get; set; }
|
||||
public abstract double Area { get; }
|
||||
}
|
||||
22
vscode/Chapter09/Chapter09.code-workspace
Normal file
22
vscode/Chapter09/Chapter09.code-workspace
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "WorkingWithFileSystems"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithStreams"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithEncodings"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithSerialization"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithJson"
|
||||
},
|
||||
{
|
||||
"path": "Ch09Ex02SerializingShapes"
|
||||
}
|
||||
]
|
||||
}
|
||||
51
vscode/Chapter09/WorkingWithEncodings/Program.cs
Normal file
51
vscode/Chapter09/WorkingWithEncodings/Program.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using Packt.Shared;
|
||||
using System.Text;
|
||||
|
||||
WriteLine("Encodings");
|
||||
WriteLine("[1] ASCII");
|
||||
WriteLine("[2] UTF-7");
|
||||
WriteLine("[3] UTF-8");
|
||||
WriteLine("[4] UTF-16 (Unicode)");
|
||||
WriteLine("[5] UTF-32");
|
||||
WriteLine("[6] Latin1");
|
||||
WriteLine("[any other key] Default encoding");
|
||||
WriteLine();
|
||||
|
||||
// choose an encoding
|
||||
Write("Press a number to choose an encoding.");
|
||||
ConsoleKey number = ReadKey(intercept: true).Key;
|
||||
WriteLine(); WriteLine();
|
||||
|
||||
Encoding encoder = number switch
|
||||
{
|
||||
ConsoleKey.D1 or ConsoleKey.NumPad1 => Encoding.ASCII,
|
||||
ConsoleKey.D2 or ConsoleKey.NumPad2 => Encoding.UTF7,
|
||||
ConsoleKey.D3 or ConsoleKey.NumPad3 => Encoding.UTF8,
|
||||
ConsoleKey.D4 or ConsoleKey.NumPad4 => Encoding.Unicode,
|
||||
ConsoleKey.D5 or ConsoleKey.NumPad5 => Encoding.UTF32,
|
||||
ConsoleKey.D6 or ConsoleKey.NumPad6 => Encoding.Latin1,
|
||||
_ => Encoding.Default
|
||||
};
|
||||
|
||||
// define a string to encode
|
||||
string message = "Café £4.39";
|
||||
WriteLine($"Text to encode: {message} Characters: {message.Length}");
|
||||
|
||||
// encode the string into a byte array
|
||||
byte[] encoded = encoder.GetBytes(message);
|
||||
|
||||
// check how many bytes the encoding needed
|
||||
WriteLine("{0} used {1:N0} bytes.",
|
||||
encoder.GetType().Name, encoded.Length);
|
||||
WriteLine();
|
||||
|
||||
// enumerate each byte
|
||||
WriteLine($"BYTE | HEX | CHAR");
|
||||
foreach (byte b in encoded)
|
||||
{
|
||||
WriteLine($"{b,4} | {b.ToString("X"),3} | {(char)b,4}");
|
||||
}
|
||||
|
||||
// decode the byte array back into a string and display it
|
||||
string decoded = encoder.GetString(encoded);
|
||||
WriteLine(decoded);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
12
vscode/Chapter09/WorkingWithFileSystems/Program.Helpers.cs
Normal file
12
vscode/Chapter09/WorkingWithFileSystems/Program.Helpers.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
partial class Program
|
||||
{
|
||||
static void SectionTitle(string title)
|
||||
{
|
||||
ConsoleColor previousColor = ForegroundColor;
|
||||
ForegroundColor = ConsoleColor.Yellow;
|
||||
WriteLine("*");
|
||||
WriteLine($"* {title}");
|
||||
WriteLine("*");
|
||||
ForegroundColor = previousColor;
|
||||
}
|
||||
}
|
||||
132
vscode/Chapter09/WorkingWithFileSystems/Program.cs
Normal file
132
vscode/Chapter09/WorkingWithFileSystems/Program.cs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
using static System.IO.Directory;
|
||||
using static System.IO.Path;
|
||||
using static System.Environment;
|
||||
|
||||
SectionTitle("Handling cross-platform environments and filesystems");
|
||||
|
||||
WriteLine("{0,-33} {1}", arg0: "Path.PathSeparator",
|
||||
arg1: PathSeparator);
|
||||
WriteLine("{0,-33} {1}", arg0: "Path.DirectorySeparatorChar",
|
||||
arg1: DirectorySeparatorChar);
|
||||
WriteLine("{0,-33} {1}", arg0: "Directory.GetCurrentDirectory()",
|
||||
arg1: GetCurrentDirectory());
|
||||
WriteLine("{0,-33} {1}", arg0: "Environment.CurrentDirectory",
|
||||
arg1: CurrentDirectory);
|
||||
WriteLine("{0,-33} {1}", arg0: "Environment.SystemDirectory",
|
||||
arg1: SystemDirectory);
|
||||
WriteLine("{0,-33} {1}", arg0: "Path.GetTempPath()",
|
||||
arg1: GetTempPath());
|
||||
WriteLine("GetFolderPath(SpecialFolder");
|
||||
WriteLine("{0,-33} {1}", arg0: " .System)",
|
||||
arg1: GetFolderPath(SpecialFolder.System));
|
||||
WriteLine("{0,-33} {1}", arg0: " .ApplicationData)",
|
||||
arg1: GetFolderPath(SpecialFolder.ApplicationData));
|
||||
WriteLine("{0,-33} {1}", arg0: " .MyDocuments)",
|
||||
arg1: GetFolderPath(SpecialFolder.MyDocuments));
|
||||
WriteLine("{0,-33} {1}", arg0: " .Personal)",
|
||||
arg1: GetFolderPath(SpecialFolder.Personal));
|
||||
|
||||
SectionTitle("Managing drives");
|
||||
|
||||
WriteLine("{0,-30} | {1,-10} | {2,-7} | {3,18} | {4,18}",
|
||||
"NAME", "TYPE", "FORMAT", "SIZE (BYTES)", "FREE SPACE");
|
||||
|
||||
foreach (DriveInfo drive in DriveInfo.GetDrives())
|
||||
{
|
||||
if (drive.IsReady)
|
||||
{
|
||||
WriteLine(
|
||||
"{0,-30} | {1,-10} | {2,-7} | {3,18:N0} | {4,18:N0}",
|
||||
drive.Name, drive.DriveType, drive.DriveFormat,
|
||||
drive.TotalSize, drive.AvailableFreeSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine("{0,-30} | {1,-10}", drive.Name, drive.DriveType);
|
||||
}
|
||||
}
|
||||
|
||||
SectionTitle("Managing directories");
|
||||
|
||||
// define a directory path for a new folder
|
||||
// starting in the user's folder
|
||||
string newFolder = Combine(
|
||||
GetFolderPath(SpecialFolder.Personal), "NewFolder");
|
||||
|
||||
WriteLine($"Working with: {newFolder}");
|
||||
|
||||
// check if it exists
|
||||
WriteLine($"Does it exist? {Exists(newFolder)}");
|
||||
|
||||
// create directory
|
||||
WriteLine("Creating it...");
|
||||
CreateDirectory(newFolder);
|
||||
WriteLine($"Does it exist? {Exists(newFolder)}");
|
||||
Write("Confirm the directory exists, and then press ENTER: ");
|
||||
ReadLine();
|
||||
|
||||
// delete directory
|
||||
WriteLine("Deleting it...");
|
||||
Delete(newFolder, recursive: true);
|
||||
WriteLine($"Does it exist? {Exists(newFolder)}");
|
||||
|
||||
SectionTitle("Managing files");
|
||||
|
||||
// define a directory path to output files
|
||||
// starting in the user's folder
|
||||
string dir = Combine(
|
||||
GetFolderPath(SpecialFolder.Personal), "OutputFiles");
|
||||
|
||||
CreateDirectory(dir);
|
||||
|
||||
// define file paths
|
||||
string textFile = Combine(dir, "Dummy.txt");
|
||||
string backupFile = Combine(dir, "Dummy.bak");
|
||||
WriteLine($"Working with: {textFile}");
|
||||
|
||||
// check if a file exists
|
||||
WriteLine($"Does it exist? {File.Exists(textFile)}");
|
||||
|
||||
// create a new text file and write a line to it
|
||||
StreamWriter textWriter = File.CreateText(textFile);
|
||||
textWriter.WriteLine("Hello, C#!");
|
||||
textWriter.Close(); // close file and release resources
|
||||
WriteLine($"Does it exist? {File.Exists(textFile)}");
|
||||
|
||||
// copy the file, and overwrite if it already exists
|
||||
File.Copy(sourceFileName: textFile,
|
||||
destFileName: backupFile, overwrite: true);
|
||||
|
||||
WriteLine(
|
||||
$"Does {backupFile} exist? {File.Exists(backupFile)}");
|
||||
|
||||
Write("Confirm the files exist, and then press ENTER: ");
|
||||
ReadLine();
|
||||
|
||||
// delete file
|
||||
File.Delete(textFile);
|
||||
WriteLine($"Does it exist? {File.Exists(textFile)}");
|
||||
|
||||
// read from the text file backup
|
||||
WriteLine($"Reading contents of {backupFile}:");
|
||||
StreamReader textReader = File.OpenText(backupFile);
|
||||
WriteLine(textReader.ReadToEnd());
|
||||
textReader.Close();
|
||||
|
||||
SectionTitle("Managing paths");
|
||||
|
||||
WriteLine($"Folder Name: {GetDirectoryName(textFile)}");
|
||||
WriteLine($"File Name: {GetFileName(textFile)}");
|
||||
WriteLine("File Name without Extension: {0}",
|
||||
GetFileNameWithoutExtension(textFile));
|
||||
WriteLine($"File Extension: {GetExtension(textFile)}");
|
||||
WriteLine($"Random File Name: {GetRandomFileName()}");
|
||||
WriteLine($"Temporary File Name: {GetTempFileName()}");
|
||||
|
||||
SectionTitle("Getting file information ");
|
||||
|
||||
FileInfo info = new(backupFile);
|
||||
WriteLine($"{backupFile}:");
|
||||
WriteLine($"Contains {info.Length} bytes");
|
||||
WriteLine($"Last accessed {info.LastAccessTime}");
|
||||
WriteLine($"Has readonly set to {info.IsReadOnly}");
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
23
vscode/Chapter09/WorkingWithJson/Book.cs
Normal file
23
vscode/Chapter09/WorkingWithJson/Book.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using System.Text.Json.Serialization; // [JsonInclude]
|
||||
|
||||
public class Book
|
||||
{
|
||||
// constructor to set non-nullable property
|
||||
public Book(string title)
|
||||
{
|
||||
Title = title;
|
||||
}
|
||||
|
||||
// properties
|
||||
public string Title { get; set; }
|
||||
public string? Author { get; set; }
|
||||
|
||||
// fields
|
||||
[JsonInclude] // include this field
|
||||
public DateTime PublishDate;
|
||||
|
||||
[JsonInclude] // include this field
|
||||
public DateTimeOffset Created;
|
||||
|
||||
public ushort Pages;
|
||||
}
|
||||
39
vscode/Chapter09/WorkingWithJson/Program.cs
Normal file
39
vscode/Chapter09/WorkingWithJson/Program.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using System.Text.Json; // JsonSerializer
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
Book mybook = new(title:
|
||||
"C# 11 and .NET 7 - Modern Cross-platform Development")
|
||||
{
|
||||
Author = "Mark J Price",
|
||||
PublishDate = new(year: 2022, month: 11, day: 8),
|
||||
Pages = 823,
|
||||
Created = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
JsonSerializerOptions options = new()
|
||||
{
|
||||
/*
|
||||
IncludeFields = true, // includes all fields
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
*/
|
||||
};
|
||||
|
||||
string filePath = Combine(CurrentDirectory, "mybook.json");
|
||||
|
||||
using (Stream fileStream = File.Create(filePath))
|
||||
{
|
||||
JsonSerializer.Serialize<Book>(
|
||||
utf8Json: fileStream, value: mybook, options);
|
||||
}
|
||||
|
||||
WriteLine("Written {0:N0} bytes of JSON to {1}",
|
||||
arg0: new FileInfo(filePath).Length,
|
||||
arg1: filePath);
|
||||
WriteLine();
|
||||
|
||||
// Display the serialized object graph
|
||||
WriteLine(File.ReadAllText(filePath));
|
||||
14
vscode/Chapter09/WorkingWithJson/WorkingWithJson.csproj
Normal file
14
vscode/Chapter09/WorkingWithJson/WorkingWithJson.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
26
vscode/Chapter09/WorkingWithSerialization/Person.cs
Normal file
26
vscode/Chapter09/WorkingWithSerialization/Person.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using System.Xml.Serialization; // [XmlAttribute]
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
public class Person
|
||||
{
|
||||
public Person() { }
|
||||
|
||||
public Person(decimal initialSalary)
|
||||
{
|
||||
Salary = initialSalary;
|
||||
}
|
||||
|
||||
[XmlAttribute("fname")]
|
||||
public string? FirstName { get; set; }
|
||||
|
||||
[XmlAttribute("lname")]
|
||||
public string? LastName { get; set; }
|
||||
|
||||
[XmlAttribute("dob")]
|
||||
public DateTime DateOfBirth { get; set; }
|
||||
|
||||
public HashSet<Person>? Children { get; set; }
|
||||
|
||||
protected decimal Salary { get; set; }
|
||||
}
|
||||
117
vscode/Chapter09/WorkingWithSerialization/Program.cs
Normal file
117
vscode/Chapter09/WorkingWithSerialization/Program.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
using System.Xml.Serialization; // XmlSerializer
|
||||
using Packt.Shared; // Person
|
||||
using NewJson = System.Text.Json.JsonSerializer;
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
// create an object graph
|
||||
List<Person> people = new()
|
||||
{
|
||||
new(30000M)
|
||||
{
|
||||
FirstName = "Alice",
|
||||
LastName = "Smith",
|
||||
DateOfBirth = new(year: 1974, month: 3, day: 14)
|
||||
},
|
||||
new(40000M)
|
||||
{
|
||||
FirstName = "Bob",
|
||||
LastName = "Jones",
|
||||
DateOfBirth = new(year: 1969, month: 11, day: 23)
|
||||
},
|
||||
new(20000M)
|
||||
{
|
||||
FirstName = "Charlie",
|
||||
LastName = "Cox",
|
||||
DateOfBirth = new(year: 1984, month: 5, day: 4),
|
||||
Children = new()
|
||||
{
|
||||
new(0M)
|
||||
{
|
||||
FirstName = "Sally",
|
||||
LastName = "Cox",
|
||||
DateOfBirth = new(year: 2012, month: 7, day: 12)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// create object that will format a List of Persons as XML
|
||||
XmlSerializer xs = new(type: people.GetType());
|
||||
|
||||
// create a file to write to
|
||||
string path = Combine(CurrentDirectory, "people.xml");
|
||||
|
||||
using (FileStream stream = File.Create(path))
|
||||
{
|
||||
// serialize the object graph to the stream
|
||||
xs.Serialize(stream, people);
|
||||
}
|
||||
|
||||
WriteLine("Written {0:N0} bytes of XML to {1}",
|
||||
arg0: new FileInfo(path).Length,
|
||||
arg1: path);
|
||||
WriteLine();
|
||||
|
||||
// Display the serialized object graph
|
||||
WriteLine(File.ReadAllText(path));
|
||||
|
||||
WriteLine();
|
||||
WriteLine("* Deserializing XML files");
|
||||
|
||||
using (FileStream xmlLoad = File.Open(path, FileMode.Open))
|
||||
{
|
||||
// deserialize and cast the object graph into a List of Person
|
||||
List<Person>? loadedPeople =
|
||||
xs.Deserialize(xmlLoad) as List<Person>;
|
||||
|
||||
if (loadedPeople is not null)
|
||||
{
|
||||
foreach (Person p in loadedPeople)
|
||||
{
|
||||
WriteLine("{0} has {1} children.",
|
||||
p.LastName, p.Children?.Count ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a file to write to
|
||||
string jsonPath = Combine(CurrentDirectory, "people.json");
|
||||
|
||||
using (StreamWriter jsonStream = File.CreateText(jsonPath))
|
||||
{
|
||||
// create an object that will format as JSON
|
||||
Newtonsoft.Json.JsonSerializer jss = new();
|
||||
|
||||
// serialize the object graph into a string
|
||||
jss.Serialize(jsonStream, people);
|
||||
}
|
||||
|
||||
WriteLine();
|
||||
WriteLine("Written {0:N0} bytes of JSON to: {1}",
|
||||
arg0: new FileInfo(jsonPath).Length,
|
||||
arg1: jsonPath);
|
||||
|
||||
// Display the serialized object graph
|
||||
WriteLine(File.ReadAllText(jsonPath));
|
||||
|
||||
WriteLine();
|
||||
WriteLine("* Deserializing JSON files");
|
||||
|
||||
using (FileStream jsonLoad = File.Open(jsonPath, FileMode.Open))
|
||||
{
|
||||
// deserialize object graph into a List of Person
|
||||
List<Person>? loadedPeople =
|
||||
await NewJson.DeserializeAsync(utf8Json: jsonLoad,
|
||||
returnType: typeof(List<Person>)) as List<Person>;
|
||||
|
||||
if (loadedPeople is not null)
|
||||
{
|
||||
foreach (Person p in loadedPeople)
|
||||
{
|
||||
WriteLine("{0} has {1} children.",
|
||||
p.LastName, p.Children?.Count ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
78
vscode/Chapter09/WorkingWithStreams/Program.Compress.cs
Normal file
78
vscode/Chapter09/WorkingWithStreams/Program.Compress.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
using System.IO.Compression; // BrotliStream, GZipStream, CompressionMode
|
||||
using System.Xml; // XmlWriter, XmlReader
|
||||
|
||||
using static System.Environment; // CurrentDirectory
|
||||
using static System.IO.Path; // Combine
|
||||
|
||||
partial class Program
|
||||
{
|
||||
static void Compress(string algorithm = "gzip")
|
||||
{
|
||||
// define a file path using algorithm as file extension
|
||||
string filePath = Combine(
|
||||
CurrentDirectory, $"streams.{algorithm}");
|
||||
|
||||
FileStream file = File.Create(filePath);
|
||||
Stream compressor;
|
||||
if (algorithm == "gzip")
|
||||
{
|
||||
compressor = new GZipStream(file, CompressionMode.Compress);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressor = new BrotliStream(file, CompressionMode.Compress);
|
||||
}
|
||||
|
||||
using (compressor)
|
||||
{
|
||||
using (XmlWriter xml = XmlWriter.Create(compressor))
|
||||
{
|
||||
xml.WriteStartDocument();
|
||||
xml.WriteStartElement("callsigns");
|
||||
foreach (string item in Viper.Callsigns)
|
||||
{
|
||||
xml.WriteElementString("callsign", item);
|
||||
}
|
||||
}
|
||||
} // also closes the underlying stream
|
||||
|
||||
// output all the contents of the compressed file
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
filePath, new FileInfo(filePath).Length);
|
||||
|
||||
WriteLine($"The compressed contents:");
|
||||
WriteLine(File.ReadAllText(filePath));
|
||||
|
||||
// read a compressed file
|
||||
WriteLine("Reading the compressed XML file:");
|
||||
file = File.Open(filePath, FileMode.Open);
|
||||
Stream decompressor;
|
||||
if (algorithm == "gzip")
|
||||
{
|
||||
decompressor = new GZipStream(
|
||||
file, CompressionMode.Decompress);
|
||||
}
|
||||
else
|
||||
{
|
||||
decompressor = new BrotliStream(
|
||||
file, CompressionMode.Decompress);
|
||||
}
|
||||
|
||||
using (decompressor)
|
||||
{
|
||||
using (XmlReader reader = XmlReader.Create(decompressor))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
// check if we are on an element node named callsign
|
||||
if ((reader.NodeType == XmlNodeType.Element)
|
||||
&& (reader.Name == "callsign"))
|
||||
{
|
||||
reader.Read(); // move to the text inside element
|
||||
WriteLine($"{reader.Value}"); // read its value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
vscode/Chapter09/WorkingWithStreams/Program.Helpers.cs
Normal file
12
vscode/Chapter09/WorkingWithStreams/Program.Helpers.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
partial class Program
|
||||
{
|
||||
static void SectionTitle(string title)
|
||||
{
|
||||
ConsoleColor previousColor = ForegroundColor;
|
||||
ForegroundColor = ConsoleColor.Yellow;
|
||||
WriteLine("*");
|
||||
WriteLine($"* {title}");
|
||||
WriteLine("*");
|
||||
ForegroundColor = previousColor;
|
||||
}
|
||||
}
|
||||
94
vscode/Chapter09/WorkingWithStreams/Program.cs
Normal file
94
vscode/Chapter09/WorkingWithStreams/Program.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
using System.Xml;
|
||||
|
||||
using static System.Environment;
|
||||
using static System.IO.Path;
|
||||
|
||||
SectionTitle("Writing to text streams");
|
||||
|
||||
// define a file to write to
|
||||
string textFile = Combine(CurrentDirectory, "streams.txt");
|
||||
|
||||
// create a text file and return a helper writer
|
||||
StreamWriter text = File.CreateText(textFile);
|
||||
|
||||
// enumerate the strings, writing each one
|
||||
// to the stream on a separate line
|
||||
foreach (string item in Viper.Callsigns)
|
||||
{
|
||||
text.WriteLine(item);
|
||||
}
|
||||
text.Close(); // release resources
|
||||
|
||||
// output the contents of the file
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: textFile,
|
||||
arg1: new FileInfo(textFile).Length);
|
||||
|
||||
WriteLine(File.ReadAllText(textFile));
|
||||
|
||||
SectionTitle("Writing to XML streams");
|
||||
|
||||
// define a file path to write to
|
||||
string xmlFile = Combine(CurrentDirectory, "streams.xml");
|
||||
|
||||
// declare variables for the filestream and XML writer
|
||||
FileStream? xmlFileStream = null;
|
||||
XmlWriter? xml = null;
|
||||
|
||||
try
|
||||
{
|
||||
// create a file stream
|
||||
xmlFileStream = File.Create(xmlFile);
|
||||
|
||||
// wrap the file stream in an XML writer helper
|
||||
// and automatically indent nested elements
|
||||
xml = XmlWriter.Create(xmlFileStream,
|
||||
new XmlWriterSettings { Indent = true });
|
||||
|
||||
// write the XML declaration
|
||||
xml.WriteStartDocument();
|
||||
|
||||
// write a root element
|
||||
xml.WriteStartElement("callsigns");
|
||||
|
||||
// enumerate the strings writing each one to the stream
|
||||
foreach (string item in Viper.Callsigns)
|
||||
{
|
||||
xml.WriteElementString("callsign", item);
|
||||
}
|
||||
|
||||
// write the close root element
|
||||
xml.WriteEndElement();
|
||||
|
||||
// close helper and stream
|
||||
xml.Close();
|
||||
xmlFileStream.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// if the path doesn't exist the exception will be caught
|
||||
WriteLine($"{ex.GetType()} says {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (xml != null)
|
||||
{
|
||||
xml.Dispose();
|
||||
WriteLine("The XML writer's unmanaged resources have been disposed.");
|
||||
if (xmlFileStream != null)
|
||||
{
|
||||
xmlFileStream.Dispose();
|
||||
WriteLine("The file stream's unmanaged resources have been disposed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// output all the contents of the file
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: xmlFile,
|
||||
arg1: new FileInfo(xmlFile).Length);
|
||||
WriteLine(File.ReadAllText(xmlFile));
|
||||
|
||||
SectionTitle("Compressing streams");
|
||||
Compress(algorithm: "gzip");
|
||||
Compress(algorithm: "brotli");
|
||||
9
vscode/Chapter09/WorkingWithStreams/Viper.cs
Normal file
9
vscode/Chapter09/WorkingWithStreams/Viper.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
static class Viper
|
||||
{
|
||||
// define an array of Viper pilot call signs
|
||||
public static string[] Callsigns = new[]
|
||||
{
|
||||
"Husker", "Starbuck", "Apollo", "Boomer",
|
||||
"Bulldog", "Athena", "Helo", "Racetrack"
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in a new issue