Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1150 Chapter 25: File I/O and Streams file. (If you want to display only the filenames, you could use the Directory class’s GetFiles() method, which returns a simple string array of filenames.) Figure 25-4 Listing 25-6 shows how to use the TreeView control’s SelectedNodeChanged event to bind your GridView with the file information. Listing 25-6: Binding a GridView to directory files VB < script runat="server" > Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) If (Not Page.IsPostBack) Then For Each drive As System.IO.DriveInfo In System.IO.DriveInfo.GetDrives() Dim node As TreeNode = New TreeNode() node.Value = drive.Name If (drive.IsReady) Then node.Text = drive.Name & _ " - (free space: " & drive.AvailableFreeSpace & ")" LoadDirectories(node, drive.Name) Else node.Text = drive.Name & " - (not ready)" End If Me.TreeView1.Nodes.Add(node) Next End If Me.TreeView1.CollapseAll() Continued 1150 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1151 Chapter 25: File I/O and Streams End Sub Private Sub LoadDirectories(ByVal parent As TreeNode, ByVal path As String) Dim directory As System.IO.DirectoryInfo = _ New System.IO.DirectoryInfo(path) Try For Each d As System.IO.DirectoryInfo In directory.GetDirectories() Dim node As TreeNode = New TreeNode(d.Name, d.FullName) parent.ChildNodes.Add(node) ’Recurse the current directory LoadDirectories(node, d.FullName) Next Catch ex As System.UnauthorizedAccessException parent.Text += " (Access Denied)" Catch ex As Exception parent.Text += " (Unknown Error: " + ex.Message + ")" End Try End Sub Protected Sub TreeView1_SelectedNodeChanged _ (ByVal sender As Object, ByVal e As System.EventArgs) Dim directory As System.IO.DirectoryInfo = _ New System.IO.DirectoryInfo(Me.TreeView1.SelectedNode.Value) Me.GridView1.DataSource = directory.GetFiles() Me.GridView1.DataBind() End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > Binding a Gridview < /title > < /head > < body > < form id="form1" runat="server" > < div > < table > < tr > < td style="width: 100px" valign="top" > < asp:TreeView ID="TreeView1" runat="server" OnSelectedNodeChanged="TreeView1_SelectedNodeChanged" > < /asp:TreeView > < /td > < td valign=top > < asp:GridView ID="GridView1" runat="server" AutoGenerateColumns=False GridLines=None CellPadding=3 > Continued 1151 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1152 Chapter 25: File I/O and Streams < Columns > < asp:BoundField DataField="Name" HeaderText="Name" HeaderStyle-HorizontalAlign=Left HeaderStyle-Font-Bold=true / > < asp:BoundField DataField="Length" HeaderText="Size" ItemStyle-HorizontalAlign=Right HeaderStyle-HorizontalAlign=Right HeaderStyle-Font-Bold=true / > < asp:BoundField DataField="LastWriteTime" HeaderText="Date Modified" HeaderStyle-HorizontalAlign=Left HeaderStyle-Font-Bold=true / > < /Columns > < /asp:GridView > < /td > < /tr > < /table > < /div > < /form > < /body > < /html > C# < script runat="server" > protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { foreach (System.IO.DriveInfo drive in System.IO.DriveInfo.GetDrives()) { TreeNode node = new TreeNode(); node.Value = drive.Name; // Make sure the drive is ready before we access it if (drive.IsReady) { node.Text = drive.Name + " - (free space: " + drive.AvailableFreeSpace + ")"; LoadDirectories(node, drive.Name); } else node.Text = drive.Name + " - (not ready)"; this.TreeView1.Nodes.Add(node); } } this.TreeView1.CollapseAll(); } Continued 1152 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1153 Chapter 25: File I/O and Streams private void LoadDirectories(TreeNode parent, string path) { System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(path); try { foreach (System.IO.DirectoryInfo d in directory.GetDirectories()) { TreeNode node = new TreeNode(d.Name, d.FullName); parent.ChildNodes.Add(node); //Recurse the current directory LoadDirectories(node, d.FullName); } } catch (System.UnauthorizedAccessException e) { parent.Text += " (Access Denied)"; } catch (Exception e) { parent.Text += " (Unknown Error: " + e.Message + ")"; } } protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e) { System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(this.TreeView1.SelectedNode.Value); this.GridView1.DataSource = directory.GetFiles(); this.GridView1.DataBind(); } < /script > Figure 25-5 shows what your Web page looks like after you have selected a directory and your grid has been bound to the FileInfo array. Keep in mind that, as in the Load Directory example, you can also enumerate though the FileInfo array to display the information. Listing 25-7 shows you how to enumerate through the FileInfo array and display the properties to the page. Listing 25-7: Manually enumerating directory files VB Dim dir as New System.IO.DirectoryInfo("C: \ ") For Each file as System.IO.FileInfo In dir.GetFiles("*.*") Response.Write(file.Name & " < BR > ") Response.Write(file.LastWriteTime.ToString() & " < BR > ") Response.Write(file.Attributes.ToString() & " < BR > ") Next Continued 1153 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1154 Chapter 25: File I/O and Streams C# System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(@"C: \ "); foreach (System.IO.FileInfo file in dir.GetFiles("*.*")) { Response.Write(file.Name + " < BR > "); Response.Write(file.LastWriteTime.ToString() + " < BR > "); Response.Write(file.Attributes.ToString() + " < BR > "); } Figure 25-5 Listing 25-7 also shows that you can provide a file filter to the GetFiles() method.Thisallowsyouto limit the results from the method to specific file extensions or to files matching a specific filename part. Working with Paths Although working with files and directories has been pretty easy, even going all the way back to good old ASP, one of the most problematic areas has always been working with paths. Many lines of code have been written by developers to deal with concatenating partial paths together, making sure files have extensions, evaluating those extensions, stripping filenames off of paths, and even more. Thankfully, the .NET Framework provides you with a class just for dealing with paths. The System.IO.Path class exposes a handful of static methods that make dealing with paths a snap. The following table lists the static methods exposed by the Path class. 1154 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1155 Chapter 25: File I/O and Streams Method Description ChangeExtension Changes the extension of the provided path string to the provided new extension. Combine Returns a single combined path from two partial path strings. GetDirectoryName Returns the directory or directories of the provided path. GetExtension Returns the extension of the provided path. GetFileName Returns the filename of the provided path. GetFileNameWithoutExtension Returns the filename without its extension of the provided path. GetFullPath Given a non-rooted path, returns a rooted pathname based on the current working directory. For example, if the path passed in is "temp" and the current working directory is c: \ MyWebsite ,the method returns C: \ MyWebsite \ temp . GetInvalidFileNameChars Returns an array of characters that are not allowed in filenames for the current system. GetInvalidPathChars Returns an array of characters that are not allowed in pathnames for the current system. GetPathRoot Returns the root path. GetTempFileName Returns a temporary filename, located in the temporary directory returned by GetTempPath . GetTempPath Returns the temporary directory name. HasExtension Returns a Boolean value indicating whether a path has an extension. IsPathRooted Returns a Boolean indicating if a path is rooted. As an example of using the Path class, the application shown in Figure 25-6 lets you enter a path and then displays the component parts of the path such as the root path (logical drive), the directory, filename, and extension. The GetInvalidPathChars and GetInvalidFileNameChars methods return an array of characters that are not allowed in path and filenames, respectively. Although the specific invalid characters are dependent on the platform the application is running on, the arrays returned by these methods will most likely contain elements such as non-printable characters, special Unicode characters, or characters from non-Latin–based character sets. The characters that your browser is capable of rendering will depend on your specific platform setup. Characters that your browser is incapable of rendering properly will display as the generic square box shown in Figure 25-6. The code in Listing 25-8 shows how the various methods and constant properties of the Path class have been used to create the application shown in Figure 25-6. 1155 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1156 Chapter 25: File I/O and Streams Figure 25-6 Listing 25-8: Using the Path class VB < %@ Import Namespace="System.IO" % > < script runat="server" > Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) If Page.IsPostBack Then Me.lblRootPath.Text = Path.GetPathRoot(Me.txtPathName.Text) Me.lblDirectoryName.Text = Path.GetDirectoryName(Me.txtPathName.Text) Me.lblFileName.Text = Path.GetFileName(Me.txtPathName.Text) Me.lblFileNameWithoutExtension.Text = _ Path.GetFileNameWithoutExtension(Me.txtPathName.Text) Me.lblExtension.Text = Path.GetExtension(Me.txtPathName.Text) Me.lblTemporaryPath.Text = Path.GetTempPath() Me.lblDirectorySeparatorChar.Text = _ Path.DirectorySeparatorChar.ToString() Me.lblAltDirectorySeparatorChar.Text = _ Path.AltDirectorySeparatorChar.ToString() Me.lblVolumeSeparatorChar.Text = Path.VolumeSeparatorChar.ToString() Me.lblPathSeparator.Text = Path.PathSeparator.ToString() Me.lblInvalidChars.Text = _ HttpUtility.HtmlEncode(New String(Path.GetInvalidPathChars())) Continued 1156 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1157 Chapter 25: File I/O and Streams Me.lblInvalidFileNameChars.Text = _ HttpUtility.HtmlEncode(New String(Path.GetInvalidFileNameChars())) End If End Sub < /script > < html xmlns="http://www.w3.org/1999/xhtml" > < head runat="server" > < title > Using the Path Class < /title > < /head > < body > < form id="form1" runat="server" > < div > Working with the Path Class < br / > < br / > Enter a path name: < asp:TextBox ID="txtPathName" runat="server" >< /asp:TextBox >< br / > < asp:Button ID="Button1" runat="server" Text="Button" / >< br / > < br / > Root Path = < asp:Label ID="lblRootPath" runat="server" Text="Label" / > < br / > Directory = < asp:Label ID="lblDirectoryName" runat="server" Text="Label" / > < br / > Filename = < asp:Label ID="lblFileName" runat="server" Text="Label" / > < br / > Filename (without extension) = < asp:Label ID="lblFileNameWithoutExtension" runat="server" Text="Label" / > < br / > Extension = < asp:Label ID="lblExtension" runat="server" Text="Label" / > < br / > < br / > Temporary Directory = < asp:Label ID="lblTemporaryPath" runat="server" Text="Label" / > < br / > Directory Separator Character = < asp:Label ID="lblDirectorySeparatorChar" runat="server" Text="Label" / > < br / > Alt Directory Separator Character = < asp:Label ID="lblAltDirectorySeparatorChar" runat="server" Text="Label" / > < br / > Volume Separator Character = < asp:Label ID="lblVolumeSeparatorChar" runat="server" Text="Label" / > < br / > Path Separator Character = < asp:Label ID="lblPathSeparator" runat="server" Text="Label" / > < br / > Invalid Path Characters = < asp:Label ID="lblInvalidChars" runat="server" Text="Label" / > < br / > Invalid FileName Characters = Continued 1157 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1158 Chapter 25: File I/O and Streams < asp:Label ID="lblInvalidFileNameChars" runat="server" Text="Label" / > < /div > < /form > < /body > < /html > C# < %@ Import Namespace="System.IO" % > < script runat="server" > protected void Page_Load(object sender, EventArgs e) { if (Page.IsPostBack) { this.lblRootPath.Text = Path.GetPathRoot(this.txtPathName.Text); this.lblDirectoryName.Text = Path.GetDirectoryName(this.txtPathName.Text); this.lblFileName.Text = Path.GetFileName(this.txtPathName.Text); this.lblFileNameWithoutExtension.Text = Path.GetFileNameWithoutExtension(this.txtPathName.Text); this.lblExtension.Text = Path.GetExtension(this.txtPathName.Text); this.lblTemporaryPath.Text = Path.GetTempPath(); this.lblDirectorySeparatorChar.Text = Path.DirectorySeparatorChar.ToString(); this.lblAltDirectorySeparatorChar.Text = Path.AltDirectorySeparatorChar.ToString(); this.lblVolumeSeparatorChar.Text = Path.VolumeSeparatorChar.ToString(); this.lblPathSeparator.Text = Path.PathSeparator.ToString(); this.lblInvalidChars.Text = HttpUtility.HtmlEncode( new String(Path.GetInvalidPathChars() ) ); this.lblInvalidFileNameChars.Text = HttpUtility.HtmlEncode( new String(Path.GetInvalidFileNameChars())); } } < /script > File and Directory Properties, Attributes, and Access Control Lists Finally, this section explains how you can access and modify file and directory properties, attributes, and Access Control Lists. Samples in this section use a simple text file called TextFile.txt to demonstrate the concepts. You can either create this file or substitute your own file i n the sample code. The samples assume the file has been added to the Web site and use the Server.MapPath method to determine the full filepath. 1158 Evjen c25.tex V2 - 01/28/2008 3:42pm Page 1159 Chapter 25: File I/O and Streams Properties and Attributes Files and directories share certain properties that you can use to determine the age o f a file or direc- tory, when it was last modified, and what attributes have been applied. These properties can be viewed by opening the file’s Properties dialog. You can open this dialog from Windows Explorer by either right-clicking on the file and selecting Properties from the context menu, or selecting Properties from the File menu. Figure 25-7 shows the file’s Properties window for the text document. Figure 25-7 Both the DirectoryInfo and the FileInfo classes let you access these properties and modify them. Listing 25-9 shows you an example of displaying the file properties. Listing 25-9: Displaying and modifying the file properties VB Dim file As New System.IO.FileInfo(Server.MapPath("TextFile.txt")) Response.Write("Location: " & file.FullName & " < BR > ") Response.Write("Size: " & file.Length & " < BR > ") Response.Write("Created: " & file.CreationTime & " < BR > ") Response.Write("Modified: " & file.LastWriteTime & " < BR > ") Response.Write("Accessed: " & file.LastAccessTime & " < BR > ") Response.Write("Attributes: " & file.Attributes) Continued 1159 . " < BR > ") Response.Write(file.Attributes.ToString() & " < BR > ") Next Continued 11 53 Evjen c 25. tex V2 - 01/28/2008 3: 42pm Page 1 154 Chapter 25: File I/O and Streams C# System.IO.DirectoryInfo dir = new. Path.PathSeparator.ToString() Me.lblInvalidChars.Text = _ HttpUtility.HtmlEncode(New String(Path.GetInvalidPathChars())) Continued 1 156 Evjen c 25. tex V2 - 01/28/2008 3: 42pm Page 1 157 Chapter 25: File I/O and Streams Me.lblInvalidFileNameChars.Text. 25- 7 Both the DirectoryInfo and the FileInfo classes let you access these properties and modify them. Listing 25- 9 shows you an example of displaying the file properties. Listing 25- 9: Displaying