tool development 03 - file i/o
DESCRIPTION
Chapter 03 of the lecture Tool Development taught at SAE Institute Hamburg. Introduction to WPF data controls, and files and streams in .NET.TRANSCRIPT
Tool DevelopmentChapter 03: File I/O
Nick Prühs
5 Minute Review Session
• Which WPF layout control allows you to position its children absolutely?
• Which other WPF layout panels do exist?
• Which C# keywords are related to signaling and handling exceptions, and how do they work?
• Name a few exception best practices!
• Which WPF class allows you to easily show modal dialog windows?
• Explain the difference between command, command source, command target and command binding!
2 / 58
Assignment Solution #2
DEMO
3 / 58
Objectives
• To get an overview of the data display controls ofWPF
• To learn how to approach common I/O tasks in .NET
• To understand the best practices of file and stream I/O in general
4 / 58
DataGrid Control
Provides a flexible way to display a collection of data in rows and columns.
Rendered View
5 / 58
DataGrid Control
Provides a flexible way to display a collection of data in rows and columns.
Rendered View
6 / 58
DataGrid Control
XAML
7 / 58
<DataGrid x:Name="TileTypeGrid" ItemsSource="{Binding}“ />
C#List<MapTileType> tileTypes = new List<MapTileType>
{
new MapTileType(3, "Desert"),
new MapTileType(5, "Water"),
new MapTileType(1, "Grass")
};
this.TileTypeGrid.DataContext = tileTypes;
Updating DataGrid Controls
• Updates automatically when items are added to or removed from the source data, if bound to a collection that implements the INotifyCollectionChanged interface• Example: ObservableCollection<T>
• Automatically reflects property changes, if the objects in the collection implement the INotifyPropertyChanged interface
8 / 58
DataGrid Control Content
• Generates columns automatically
• Type of column that is generated depends on the type of data in the column• String: Label
• Bool: CheckBox
• Enum: ComboBox
9 / 58
DataGrid Control Selection
• SelectionMode property specifies whether a user can select cells, full rows, or both
• SelectionUnit property specifies whether multiple rows/cells can be selected, or only single rows/cells
• SelectedCells property contains cells that are currently selected
• SelectedCellsChanged event is raised for cells for which selection has changed
10 / 58
DataGrid Control Editing
• IsReadOnly property disables editing
• CanUserAddRows and CanUserDeleteRowsproperties specify whether a user can add or delete rows
• Provides BeginEdit, CommitEdit, and CancelEditcommands
11 / 58
TreeView Control
Displays hierarchical data in a tree structure that has items that can expand and collapse.
Rendered View
12 / 58
TreeView Control
XAML
13 / 58
<TreeView>
<TreeViewItem Header="Abilities">
<TreeViewItem Header="Fireball"/>
<TreeViewItem Header="Frostbolt"/>
</TreeViewItem>
<TreeViewItem Header="Items">
<TreeViewItem Header="Ring of Dominace +3"/>
</TreeViewItem>
</TreeView>
TreeView Control
C#
14 / 58
TreeViewItem abilitiesRoot = new TreeViewItem { Header = "Abilities" };
abilitiesRoot.Items.Add(new TreeViewItem { Header = "Fireball" });
abilitiesRoot.Items.Add(new TreeViewItem { Header = "Frostbolt" });
TreeViewItem itemsRoot = new TreeViewItem { Header = "Items" };
itemsRoot.Items.Add(new TreeViewItem { Header = "Ring of Dominance +3" });
this.ObjectTree.Items.Add(abilitiesRoot);
this.ObjectTree.Items.Add(itemsRoot);
TabControl
Contains multiple items that share the same space on the screen.
Rendered View
15 / 58
TabControl
XAML
16 / 58
<TabControl>
<TabItem Header="Tab 1">
<TextBlock>Content of Tab 1</TextBlock>
</TabItem>
<TabItem Header="Tab 2">
<TextBlock>Content of Tab 2</TextBlock>
</TabItem>
</TabControl>
Streams
• Sequence of bytes read from or written to a backing store (e.g. disk, memory)
• Provide three fundamental operations:• Reading• Writing• Seeking
• Abstraction from the specific details of the operation system and underlying devices• FileStream• NetworkStream• MemoryStream• CryptoStream
17 / 58
Files
• Ordered and names collection of bytes that have persistent storage
• Disks contain directories, directories contain files
• Can be created, copied, deleted, moved, read from and written to
18 / 58
File I/O in .NET
• System.IO namespace features classes for…• Reading from files and streams
• Writing to files and streams
• Accessing file and directory information
• Readers and Writers wrap streams to handle conversion of encoded characters to and from bytes• BinaryReader, BinaryWriter
• TextReader, TextWriter
19 / 58
FileInfo Class
• Provides typical operations such as copying, moving, renaming, creating, opening, deleting, and appending to files
• Can be faster for performing multiple operations on the same file, because a security check will not always be necessary
• Grants full read/write access to new files by default
20 / 58
Creating New Files
C#
21 / 58
// Collect information on the file to create.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Create new file.
FileStream fileStream = fileInfo.Create();
// ...
// Close file stream and release all resources.
fileStream.Close();
Gotcha!
You should always release any files after you’re finished!
The user will thank you for that.
22 / 58
File In Use
23 / 78
Writing Text To Files
C#
24 / 58
// Collect information on the file to create.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Create new file.
FileStream fileStream = fileInfo.Create();
// Create new text writer.
TextWriter textWriter = new StreamWriter(fileStream);
// Write text.
textWriter.WriteLine("Hello World!");
// Close file stream and release all resources.
textWriter.Close();
Writing Encoded Text To Files
C#
25 / 58
// Collect information on the file to create.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Create new file.
FileStream fileStream = fileInfo.Create();
// Create new text writer.
TextWriter textWriter = new StreamWriter(fileStream, Encoding.UTF8);
// Write text.
textWriter.WriteLine("Hello World!");
// Close file stream and release all resources.
textWriter.Close();
Reading Text From Files
C#
26 / 58
// Collect information on the file to read from.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Open file for reading.
FileStream fileStream = fileInfo.OpenRead();
// Create new text reader.
TextReader textReader = new StreamReader(fileStream);
// Read text.
string s;
while ((s = textReader.ReadLine()) != null)
{
Console.WriteLine(s);
}
// Close file stream and release all resources.
textReader.Close();
Appending Text To Files
C#
27 / 58
// Collect information on the file to append text to.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Open file for writing.
TextWriter textWriter = fileInfo.AppendText();
// Append text.
textWriter.WriteLine("new line");
// Close file stream and release all resources.
textWriter.Close();
Renaming and Moving Files
C#
28 / 58
// Collect information on the file to rename.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Rename file.
fileInfo.MoveTo("movedFile.txt");
Deleting Files
C#
29 / 58
// Collect information on the file to delete.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Delete file.
fileInfo.Delete();
Checking Whether Files Exist
C#
30 / 58
// Collect information on the file to delete.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Check if file exists.
if (fileInfo.Exists)
{
// Delete file.
fileInfo.Delete();
}
Accessing File Info
C#
31 / 58
// Collect information on the file.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Show information on console.
Console.WriteLine("File name: {0}", fileInfo.Name);
Console.WriteLine("File size (in bytes): {0}", fileInfo.Length);
Console.WriteLine("Read-only: {0}", fileInfo.IsReadOnly);
Console.WriteLine("Modified: {0}", fileInfo.LastWriteTime);
Accessing File Info
C#
32 / 58
// Collect information on the file.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Show information on console.
Console.WriteLine("File name: {0}", fileInfo.Name);
Console.WriteLine("File size (in bytes): {0}", fileInfo.Length);
Console.WriteLine("Read-only: {0}", fileInfo.IsReadOnly);
Console.WriteLine("Modified: {0}", fileInfo.LastWriteTime);
Console OutputFile name: newFile.txt
File size (in bytes): 10
Read-only: False
Modified: 11/3/2013 3:51:13 PM
Writing Binary Data To Files
C#
33 / 58
// Collect information on the file to create.
FileInfo fileInfo = new FileInfo("newFile.dat");
// Create new file.
FileStream fileStream = fileInfo.Create();
// Create new binary writer.
BinaryWriter binaryWriter = new BinaryWriter(fileStream);
// Write data.
binaryWriter.Write(23);
binaryWriter.Write(true);
binaryWriter.Write(0.4f);
// Close file stream and release all resources.
binaryWriter.Close();
Reading From Binary Files
C#
34 / 58
// Collect information on the file to read from.
FileInfo fileInfo = new FileInfo("newFile.dat");
// Open file for reading.
FileStream fileStream = fileInfo.OpenRead();
// Create new binary reader.
BinaryReader binaryReader = new BinaryReader(fileStream);
// Read data.
int i = binaryReader.ReadInt32();
bool b = binaryReader.ReadBoolean();
float f = binaryReader.ReadSingle();
// Close file stream and release all resources.
binaryReader.Close();
File Access Rights
• When opening a file, you have to request the required access right from the underlying operating system• Read access
• Write access
• You can request either exclusive or non-exclusive access rights, possibly preventing future access to the file until you release it again
35 / 58
Exclusive Reading
C#
36 / 58
// Collect information on the file to read from.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Open file for exclusive reading.
FileStream fileStream = fileInfo.OpenRead();
// Create new text reader.
TextReader textReader = new StreamReader(fileStream);
Exclusive Reading
C#
37 / 58
// Collect information on the file to read from.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Open file for exclusive reading.
FileStream fileStream = fileInfo.Open(FileMode.Open, FileAccess.Read);
// Create new text reader.
TextReader textReader = new StreamReader(fileStream);
Shared Reading
C#
38 / 58
// Collect information on the file to read from.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Open file for shared reading.
FileStream fileStream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
// Create new text reader.
TextReader textReader = new StreamReader(fileStream);
The interface IDisposable
• Primary use of this interface is to release unmanaged resources• Garbage collector automatically releases the memory
allocated to a managed object when that object is no longer used
• However, it is not possible to predict when garbage collection will occur.
• Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams
• Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector.
39 / 78
The using Statement
• Provides a convenient syntax that ensures the correct use of IDisposable objects
• As a rule, when you use an IDisposable object, you should declare and instantiate it in a usingstatement• Calls the Dispose method on the object in the correct
way, and causes the object itself to go out of scope as soon as Dispose is called
• Ensures that Dispose is called even if an exception occurs while you are calling methods on the object
• Within the using block, the object is read-only and cannot be modified or reassigned
40 / 78
Writing Text To Files
C#
41 / 58
// Collect information on the file to create.
FileInfo fileInfo = new FileInfo("newFile.txt");
// Create new file.
using (FileStream fileStream = fileInfo.Create())
{
// Create new text writer.
using (TextWriter textWriter = new StreamWriter(fileStream, Encoding.UTF8))
{
// Write text.
textWriter.WriteLine("Hello World!");
}
}
DirectoryInfo Class
• Same as FileInfo, just for directories• Create method
• CreateSubdirectory method
• MoveTo method
• Delete method
• Exists property
• Parent property
42 / 58
Enumerating Directory Files
C#
43 / 58
// Collect information on the directory to enumerate all text files of.
DirectoryInfo directoryInfo = new DirectoryInfo(".");
// Enumerate all files in the directory.
IEnumerable<FileInfo> files = directoryInfo.EnumerateFiles("*.txt");
// Show file names on console.
foreach (FileInfo file in files)
{
Console.WriteLine(file.Name);
}
Enumerating Directory Files
C#
44 / 58
// Collect information on the directory to enumerate all text files of.
DirectoryInfo directoryInfo = new DirectoryInfo(".");
// Recursively enumerate all files in the directory.
IEnumerable<FileInfo> files = directoryInfo.EnumerateFiles("*.txt", SearchOption.AllDirectories);
// Show file names on console.
foreach (FileInfo file in files)
{
Console.WriteLine(file.FullName);
}
Compressing andExtracting DirectoriesC#
45 / 58
// Compress directory to zip file.
ZipFile.CreateFromDirectory("content", "archive.zip");
// Extract directory from zip file.
ZipFile.ExtractToDirectory("archive.zip", "extracted");
Gotcha!
To use the ZipFile class, you must reference the assembly
System.IO.Compression.FileSystem.
46 / 78
Compressing andExtracting Single FilesC#
47 / 78
const string OutputDirectory = "extracted";
if (!Directory.Exists(OutputDirectory))
{
Directory.CreateDirectory(OutputDirectory);
}
// Open zip file for reading.
using (ZipArchive archive = ZipFile.OpenRead("archive.zip"))
{
// Iterate all archive files.
foreach (ZipArchiveEntry entry in archive.Entries)
{
// Extract file.
entry.ExtractToFile(Path.Combine(OutputDirectory, entry.FullName));
}
}
Compositing Streams
• The design of the System.IO classes provides simplified stream composing
• Base streams can be attached to one or more pass-through streams that provide the functionality you want
• Reader or writer is attached to the end of the chain
48 / 58
Compositing Streams
C#
49 / 58
// Collect information on the file to create.
FileInfo fileInfo = new FileInfo("newFile.gz");
// Create new file.
using (FileStream fileStream = fileInfo.Create())
{
// Create compression stream.
using (GZipStream compressionStream = new GZipStream(fileStream, CompressionMode.Compress))
{
// Create new text writer.
using (TextWriter textWriter = new StreamWriter(compressionStream))
{
// Write text.
textWriter.WriteLine("Hello World!");
}
}
}
Common Exceptions
• UnauthorizedAccessException• Example: Destination is read-only.
• ArgumentException• Example: Destination path contains invalid characters.
• ArgumentNullException• Example: Destination path is null.
• FileNotFoundException• Example: File not found.
• IOException• Example: Destination file already exists.
50 / 58
Hint
Check MSDN documentation for thrown exceptions whenever you
work with System.IO classes.
51 / 78
Assignment #3
1. Map Sprites
1. Create a sprite (.png file) for each of your terrain types and add it to the project.
2. Load all sprites on startup of your application by creating and storing BitmapImage objects. You can access project resources in image URIs as follows:
image.UriSource = newUri("pack://application:,,,/Desert.png");
52 / 58
Assignment #3
2. Map Canvas
1. Add a canvas to your main window.
2. Reset the map canvas whenever a new map is created:
1. Remove all children.
2. Add Image children to the canvas.
3. Set the position of these children using Canvas.SetLeft and Canvas.SetTop.
53 / 58
Assignment #3
3. Scrolling
Parent the map canvas to a ScrollViewer to enable scrolling across the map.
54 / 58
Assignment #3
4. Brush
1. Add a brush selection to your main window.
2. Enable drawing on the map canvas.1. Modify the map model whenever the user clicks on a map
canvas image. You can use the Tag property of an image to store its position, and the MouseLeftButtonDown, MouseLeftButtonUp and MouseMove events for handling user input.
2. Update the map canvas with the new tile at the clicked position.
55 / 58
References
• MSDN. WPF Controls by Category. http://msdn.microsoft.com/en-us/library/ms754204%28v=vs.110%29.aspx, April 2015.
• MSDN. File and Stream I/O. http://msdn.microsoft.com/en-us/library/k3352a4t%28v=vs.110%29.aspx, April 2015.
• MSDN. Common I/O Tasks. http://msdn.microsoft.com/en-us/library/ms404278%28v=vs.110%29.aspx, April 2015.
• MSDN. using Statement (C# Reference). http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.120).aspx, April 2015.
56 / 58
Thank you for your attention!
Contact
Blog
http://www.npruehs.de
@npruehs
Github
https://github.com/npruehs
57 / 58