Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C++/CLI
Article

Basic stuff on Files, Directories and Streams

Rate me:
Please Sign up or sign in to vote.
4.93/5 (28 votes)
26 Jun 20023 min read 173.8K   938   29   15
Demonstrates the use of the reader/writer classes as well as the file/directory info classes

Introduction

Most common applications require reading and writing of files. There are numerous classes in the .NET BCL that provide various methods for creating and manipulating files and directories. In this article I'll cover the basic operations that you might have to perform with files. Since the functionality offered by most of the classes discussed here is too extensive to be completely covered, I only demonstrate some really common  uses of these classes. The readers can then explore the rest of the functionality on their own. The first version of this article used C# examples, but in this refined and expanded version I have used Managed C++. The article comprises of various techniques and is not in the form of a top-to-down tutorial. I welcome requests for more tips or techniques that readers would like to see included in the article.

Getting file information

For this we can use the System.IO.FileInfo class which has several instance methods for performing various file operations. As a short example we'll retrieve some information on Windows Notepad. I've used a native API call to retrieve the Windows directory as I couldn't figure out the .NET way of doing it. I'd be obliged if someone could tell me how to do it using .NET. Show is a user defined function that I use for a padded output.

void FileInfoDemo()
{
    TCHAR WinPath[MAX_PATH+1];
    GetWindowsDirectory(WinPath,MAX_PATH+1);
    String* NotepadPath = WinPath;
    NotepadPath = String::Concat(NotepadPath,S"\\notepad.exe");

    FileInfo* finfo = new FileInfo(NotepadPath);
    Show("Name",finfo->Name);
    Show("Directory",finfo->Directory);
    Show("Extension",finfo->Extension);
    Show("Length",__box(finfo->Length));
    Show("FullName",finfo->FullName);
    Show("CreationTime ",finfo->CreationTime.ToString()); 
}

Basically, all we do is to specify the path to the file in the constructor. Now we can use some very useful Properties to query information regarding our file. The FileInfo class has methods that return various stream readers and writers, but there are better methods to read and write to files as I'll be covering, later in this article.

Enumerate sub-directories and files

We use the DirectoryInfo class to enumerate sub-directories and files in a particular folder. It has two methods among many others called GetFiles and GetDirectories, the former returning a FileInfo array and the latter returning a DirectoryInfo array.

void DirectoryInfoDemo1()
{
    DirectoryInfo* dinfo = new DirectoryInfo("C:\\");
    DirectoryInfo* subdirs[] = dinfo->GetDirectories();
    Console::WriteLine("Sub-Directories for C:\\");
    Console::WriteLine("-----------------------");
    for(int i=0; i<subdirs->Length; i++)
        Show((i+1).ToString(),subdirs->Item[i]);
}

void DirectoryInfoDemo2()
{
    DirectoryInfo* dinfo = new DirectoryInfo("C:\\");
    FileInfo* filesindir[] = dinfo->GetFiles();
    Console::WriteLine("Files under C:\\");
    Console::WriteLine("---------------");
    for(int i=0; i<filesindir->Length; i++)
        Show((i+1).ToString(),filesindir->Item[i]); 
}

Binary files

We can read and write binary files using the BinaryReader and BinaryWriter classes. Just for fun, let's create a simple 16 bit COM format executable. We can write it using just 4 lines of 16 bit assembler as shown below. It simply calls Interrupt 21h Function 02h which outputs the character held in DL. I have also given the machine code equivalents of these assembler statements. So all we do is create an array holding these 8 bytes and then we use the BinaryWriter class to write to a file. Now we can actually run this file and it will print an 'A' on screen.

ASM
MOV AH,02h    ; B4 02
MOV DL,41h    ; B2 41
INT 21h       ; CD 21
INT 20h       ; CD 20
void BinaryWriterDemo()
{
    Console::WriteLine("Creating C:\\nish.com");
    Console::WriteLine("This will output an 'A' to the console");
    FileStream* fs = new FileStream("C:\\nish.com",
    FileMode::Create,FileAccess::Write);
    BinaryWriter* bw = new BinaryWriter(fs);
    unsigned char SomeBinaryData __gc[] = 
        {0xb4,0x02,0xb2,0x41,0xcd,0x21,0xcd,0x20};
    bw->Write(SomeBinaryData);
    bw->Flush();
    bw->Close();
}

Now I'll show you how to use the BinaryReader class to read the binary file we created above and display the bytes in the file.

void BinaryReaderDemo()
{
    Console::WriteLine("Reading C:\\nish.com");
    FileStream* fs = new FileStream("C:\\nish.com",
    FileMode::Open,FileAccess::Read);
    BinaryReader* br = new BinaryReader(fs);
    unsigned char c;
    while(br->PeekChar() != -1)
    {
        c = br->ReadByte();
        Console::Write("{0:X2} ",__box(c));
    }
    br->Close();
    Console::WriteLine();
}

One small issue with the BinaryReader.ReadByte Method is that it throws an EndOfStreamException instead of indicating it using a special return value. To avoid handling the exception and doing it the old-C style way, which may or may not be a good thing, I have used PeekChar which will return the next byte but will not move the file pointer.

Text Files

There are more than one way of reading and writing text files, but here I'll show you how to use the StreamWriter and StreamReader classes. They remind me very much of the MFC CStdioFile class. The StreamReader class has a ReadLine method and the StreamWrite class has a WriteLine method both of which are exactly similar in behaviour with the CStdioFile::ReadString and CStdioFile::WriteString methods. Both the classes have constructors that take a file path as argument and thus we don't need to create the FileStream object first as we had to do with the BinaryReader and BinaryWriter classes.

void StreamWriterDemo()
{
    Console::WriteLine("Creating C:\\TempFile.txt");
    StreamWriter *sw = new StreamWriter ("C:\\TempFile.txt");
    sw->WriteLine("This is the first line"); 
    sw->WriteLine("This is the second line"); 
    sw->WriteLine("This is the third/last line"); 
    sw->Close();
}

void StreamReaderDemo()
{
    Console::WriteLine("Reading C:\\TempFile.txt");
    Console::WriteLine("-----------------------");
    StreamReader* sr = new StreamReader ("C:\\TempFile.txt");
    String* s;
    while(s = sr->ReadLine())
        Console::WriteLine(s);
    sr->Close();
}

Reading from a string

They think of everything, don't they. StringReader is a class derived from TextReader that allows us to read from a string directly. There is also a corresponding StringWriter class. I am not very definite about it's purpose, but I guess someone would find some use for it. Maybe it might prove useful for parsing simple strings.

void StringReaderDemo(String* s)
{
    Console::WriteLine("Reading the string [{0}]",s);
    StringReader* sr = new StringReader(s);
    int c;
    while((c = sr->Read()) != -1)
        Console::Write("{0} ",__box(Convert::ToChar(c)));
    Console::WriteLine(); 
    sr->Close();
} 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
Nish Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.

Nish authored C++/CLI in Action for Manning Publications in 2005, and co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.

Nish's Technology Blog : voidnish.wordpress.com

Comments and Discussions

 
QuestionC++? Pin
speedpacer16-Jun-03 8:06
speedpacer16-Jun-03 8:06 
GeneralWindows Directory Pin
Michael G Hawksworth12-Aug-02 5:45
sussMichael G Hawksworth12-Aug-02 5:45 
GeneralRe: Windows Directory Pin
Nish Nishant14-Aug-02 18:15
sitebuilderNish Nishant14-Aug-02 18:15 
GeneralUpdated - June 27 [with some difficulty] Pin
Nish Nishant27-Jun-02 6:34
sitebuilderNish Nishant27-Jun-02 6:34 
GeneralNice basics! Pin
Martin Haesemeyer15-May-02 1:16
Martin Haesemeyer15-May-02 1:16 
GeneralRe: Nice basics! Pin
Nish Nishant15-May-02 1:26
sitebuilderNish Nishant15-May-02 1:26 
Generalusefull code Pin
Alexandr_K1-Apr-02 12:28
Alexandr_K1-Apr-02 12:28 
GeneralRe: usefull code Pin
Alexandr_K1-Apr-02 12:30
Alexandr_K1-Apr-02 12:30 
GeneralRe: usefull code Pin
Nish Nishant1-Apr-02 16:25
sitebuilderNish Nishant1-Apr-02 16:25 
GeneralRe: usefull code Pin
Nish Nishant1-Apr-02 16:24
sitebuilderNish Nishant1-Apr-02 16:24 
GeneralFileStream fs = new FileStream("nish.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite Pin
5-Mar-02 6:16
suss5-Mar-02 6:16 
GeneralConsole.Write("{0}",Convert.ToChar(b1)); Pin
Katsarakis26-Oct-01 10:29
Katsarakis26-Oct-01 10:29 
GeneralRe: Console.Write("{0}",Convert.ToChar(b1)); Pin
Nish Nishant26-Oct-01 17:03
sitebuilderNish Nishant26-Oct-01 17:03 
GeneralFileInfo f = new FileInfo ("nish.txt"); Pin
Katsarakis26-Oct-01 10:05
Katsarakis26-Oct-01 10:05 
GeneralRe: FileInfo f = new FileInfo ("nish.txt"); Pin
Nish Nishant26-Oct-01 17:07
sitebuilderNish Nishant26-Oct-01 17:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.