Sunday, May 30, 2010

programs on streams and file manipulations

Streams and File Manipulations


6.1 Introduction

A stream is a sequence of bytes. A byte is 8 bits. The Stream class and its subclasses

provide a generic view of data sources and repositories, isolating the programmer

from the specific details of the operating system and underlying devices. Streams

involve the following three operations:

1) Streams can be read from. Reading is the transfer of data from a stream into a

data structure, such as an array of bytes.

2) Streams can be written to. Writing is the transfer of data from a data structure

into a stream.

3) Streams can support seeking. Seeking is the query and modifying of the current

position within a stream.

6.2 Binary File Manipulations

System.IO.BinaryWriter and System.IO.BinaryReader can be used for writing

and reading primitive data types

byte, short, int, long, float, double, bool, char

and also the data type string and StringBuilder to a stream (binary file manipulation).

83

84 CHAPTER 6. STREAMS AND FILE MANIPULATIONS

// BinaryIO1.cs

using System;

using System.IO;

using System.Text;

class BinaryIO1

{

private static void WriteData(int i,double d,char c,bool b)

{

Stream s = File.OpenWrite("info.dat");

BinaryWriter bw = new BinaryWriter(s);

bw.Write(i);

bw.Write(d);

bw.Write(c);

bw.Write(b);

bw.Close();

s.Close();

}

private static void ReadData()

{

Stream s = File.OpenRead("info.dat");

BinaryReader br = new BinaryReader(s);

int i = br.ReadInt32();

double d = br.ReadDouble();

char c = br.ReadChar();

bool b = br.ReadBoolean();

br.Close();

s.Close();

Console.WriteLine("{0},{1},{2},{3}",i,d,c,b);

}

public static void Main(string[] args)

{

WriteData(12345,3.14159,’y’,true);

ReadData();

}

}

// BinaryIO2.cs

using System;

using System.IO;

using System.Text;

6.3. TEXT FILE MANIPULATION 85

class BinaryIO2

{

private static void WriteData(string t,StringBuilder sb)

{

Stream s = File.OpenWrite("info.dat");

BinaryWriter bw = new BinaryWriter(s);

// write length-prefixed string

bw.Write(t);

bw.Write(sb.ToString());

bw.Close();

s.Close();

}

private static void ReadData()

{

Stream s = File.OpenRead("info.dat");

BinaryReader br = new BinaryReader(s);

string t = br.ReadString();

string sb = br.ReadString();

br.Close();

s.Close();

Console.WriteLine("{0},{1}",t,sb);

}

public static void Main(string[] args)

{

StringBuilder sb = new StringBuilder("Hello World!");

WriteData("Hello Egoli",sb);

ReadData();

}

}

6.3 Text File Manipulation

Reading a text file. The class FileStream is useful for reading and writing files on

a file system, as well as other file-related operating system handles (including pipes,

standard input, standard output, and so on). FileStream buffers input and output

for better performance. The FileStrean class can open a file in one of two modes,

either synchronously or asynchronously, with signigicant performance consequences

for the synchronous methods (FileStream.Read and FileStream.Write) and the

asynchronous methods FileStream.BeginRead and FileStream.BeginWrite). Both

sets of methods will work in either mode; however, the mode will affect the performance

of these methods. FileStream defaults to opening files synchronously, but

86 CHAPTER 6. STREAMS AND FILE MANIPULATIONS

provides a constructor to open files asynchronously. FileStream objects support

random access to files using the FileStream.Seek method. The Seek method allows

the read/write position to be moved to any position within the file. This is

done with byte offset reference point parameters. The byte offset is relative to the

seek reference point, which can be the beginning, the current position, or the end

of the underlying file, as represented by the three properties of the SeekOrigin class.

We convert the array of bytes into an ASCII text for displaying it on the console.

// readfile.cs

using System;

using System.IO;

using System.Text; // for encoding

class ReadFile

{

public static void Main(string[] args)

{

Stream s = new FileStream(args[0],FileMode.Open);

int size = (int) s.Length;

byte[] buffer = new byte[size];

s.Read(buffer,0,buffer.Length);

s.Close();

string text = Encoding.ASCII.GetString(buffer);

Console.WriteLine(text);

}

}

Writing to a file (text mode). We append the text provided by the line

string text = "all the good men and women" + "\r\n";

to the file provided by args[0].

// writefile.cs

using System;

using System.IO;

using System.Text; // for encoding

class WriteFile

{

public static void Main(string[] args)

{

Stream s = new FileStream(args[0],FileMode.Append,FileAccess.Write);

6.3. TEXT FILE MANIPULATION 87

string text = "all the good men and women" + "\r\n"; // append end

// of line characters

byte[] buffer = Encoding.ASCII.GetBytes(text);

s.Write(buffer,0,buffer.Length);

s.Close(); // also flushes the stream

}

}

Writing the date and time into a file using the DateTime class..

// placeorder.cs

using System;

using System.IO;

class PlaceOrder

{

public static void Main(string[] args)

{

DateTime dt = DateTime.Now;

string today = dt.ToString("dd-MMM-yyyy");

string record = today + "
" + String.Join("
",args);

StreamWriter sw = new StreamWriter("order.txt",true);

sw.WriteLine(record);

sw.Close();

}

}

The useful classes in reading/writing text files are: StreamReader and StreamWriter.

Given the file datain.txt with the two lines

Green 4750 3000.40

Bakley 3451 2800.50

the following program reads the file line by line and displays it on the Console and

also writes it to the output file dataout.txt.

// Filemanipulation.cs

using System;

using System.IO;

class FileManipulation

{

static void Main(string[] args)

{

88 CHAPTER 6. STREAMS AND FILE MANIPULATIONS

FileInfo fr = new FileInfo(@"c:\csharp\datain.txt");

StreamReader reader = fr.OpenText();

string sline;

string[] substrings;

char[] separators = { ’ ’,’,’,’\t’ };

string name;

int ID;

float gpa;

StreamWriter writer =

new StreamWriter(@"c:\csharp\dataout.txt",false);

sline = reader.ReadLine();

while(sline != null)

{

substrings = sline.Split(separators,3);

name = substrings[0];

ID = int.Parse(substrings[1]);

gpa = float.Parse(substrings[2]);

Console.WriteLine("{0} {1} {2}",name,ID,gpa);

writer.WriteLine("{0} {1} {2}",name,ID,gpa);

sline = reader.ReadLine();

}

writer.Flush();

writer.Close();

}

}

6.4 Byte by Byte Manipulation

For reading and writing bytes we use the methods ReadByte() and WriteByte().

The type conversion to char is necessary in the following program. What happens

if we remove (char) ?

// BytebyByte.cs

using System;

using System.IO;

public class BytebyByte

{

public static void Main(string[] args)

{

FileStream s = new FileStream(args[0],FileMode.Open,FileAccess.Read,

FileShare.Read);

BufferedStream bs = new BufferedStream(s);

while(bs.Length > bs.Position)

6.4. BYTE BY BYTE MANIPULATION 89

{

Console.Write((char) bs.ReadByte()); }

}

bs.Close();

s.Close();

}

In the following example we copy byte by byte a file into another file.

// TestFile.cs

using System;

using System.IO;

class TestFile

{

static void Copy(string from,string to,int pos)

{

try

{

FileStream sin = new FileStream(from,FileMode.Open);

FileStream sout = new FileStream(to,FileMode.Create);

sin.Seek(pos,SeekOrigin.Begin);

int ch = sin.ReadByte();

while(ch >= 0)

{

sout.WriteByte((byte) ch); // type conversion

ch = sin.ReadByte();

}

sin.Close();

sout.Close();

}

catch (FileNotFoundException e)

{

Console.WriteLine("--file {0} not found",e.FileName);

}

}

public static void Main(string[] arg)

{

Copy(arg[0],arg[1],0);

}

}

90 CHAPTER 6. STREAMS AND FILE MANIPULATIONS

In the next program we count the number of curly brackets in a file.

// Oops1.cs

using System;

using System.IO;

class Oops

{

public static void Main()

{

char cl = ’{’;

int countcl = 0;

char cr = ’}’;

int countcr = 0;

FileStream fin = new FileStream("data.dat",FileMode.Open,FileAccess.Read);

BufferedStream bs = new BufferedStream(fin);

while(bs.Length > bs.Position)

{

char ch = (char) bs.ReadByte();

if(ch == cl) countcl++;

if(ch == cr) countcr++;

} // end while

fin.Close();

Console.WriteLine("countcl = " + countcl);

Console.WriteLine("countcr = " + countcr);

} // end Main

}

Exercise. Extend the program so that it also counts the number of rectangular

brackets (left and right) and parentheses (left and right).

6.5 Object Serialization

Often we want to store a complete object in a stream. This is achieved by a process

called object serialization. By serialization we mean converting an object, or a

connected graph of objects (a set of objects with some set of references to each

other), stored within memory into a linear sequence of bytes. This string of bytes

contains all of the information that was held in the object started with.

// employee.cs

using System;

6.5. OBJECT SERIALIZATION 91

using System.Runtime.Serialization;

[Serializable]

public class Employee

{

public string Name;

public string Job;

public double Salary;

public Employee(string name,string job,double salary)

{

Name = name;

Job = job;

Salary = salary;

}

public Employee() { }

// we override the ToString() method of System.Object.

// This method is invoked whenever an Employee object

// is to be converted to a string

public override string ToString()

{

return String.Format("{0} is a {1} and earns {2}",Name,Job,Salary);

}

} // end class Employee end file

In the following program we apply now object serialization to Employee.

// binsertest1.cs

using System;

using System.IO;

using System.Runtime.Serialization.Formatters.Binary;

class BinarySerializatioTest1

{

static BinaryFormatter bf = new BinaryFormatter();

private static void WriteEmployee(Employee emp)

{

Stream s = File.OpenWrite("emp.bin");

bf.Serialize(s,emp);

s.Close();

}

92 CHAPTER 6. STREAMS AND FILE MANIPULATIONS

private static void ReadEmployee()

{

Stream s = File.OpenRead("emp.bin");

Employee emp = (Employee) bf.Deserialize(s);

s.Close();

Console.WriteLine(emp); // displays emp.ToString()

}

public static void Main(string[] args)

{

Employee emp = new Employee("Jack","Clerk",44000);

WriteEmployee(emp);

ReadEmployee();

}

}

If we have more than one employee, i.e. an array we extend the program binsertest1.cs

as follows

// serialization.cs

using System;

using System.Runtime.Serialization.Formatters.Binary;

using System.IO;

class Program

{

// declare binary formatter to read/write serialized text from file

static BinaryFormatter bf = new BinaryFormatter();

static void Main(string[] args)

{

// declare array to hold employee objects

Employee[] employees = new Employee[2];

// create first and second emplyee object in the array

employees[0] = new Employee("John Miller","Salesman",15000);

employees[1] = new Employee("Jack White","Manager",16000);

// serialize employee list to file

Serialize(employees);

// derserialize employee list

DeSerialize();

6.6. XML DOCUMENTS 93

}

static void Serialize(Employee[] employees)

{

// serialize to file

Stream stream = File.OpenWrite("employees.bin");

bf.Serialize(stream,employees);

stream.Close();

Console.WriteLine("Employee list has been serialized to file");

Console.WriteLine();

}

static void DeSerialize()

{

Console.WriteLine("Reading employee list from file");

Console.WriteLine();

// deserialize from file

Stream stream = File.OpenRead("employees.bin");

Employee[] emps = (Employee[])bf.Deserialize(stream);

stream.Close();

// loop through the array and display each employee

foreach(Employee e in emps) Console.WriteLine(e);

Console.WriteLine();

}

}

6.6 XML Documents

The .NET framework provides an XML parser for reading and modifying XML documents.

Given below is the file emp.xml containing information (id,name, job,salary)

about employees. There are five employees.







John

manager

72000





Jane

steno

23000

94 CHAPTER 6. STREAMS AND FILE MANIPULATIONS





Jim

salesman

36000





Jill

clerk

45000





Jeff

CEO

105000





The program listemp.cs displays id, and salary of each employee in the file

emp.xml.

// listemp.cs

using System;

using System.Xml;

class ListEmployees

{

public static void Main()

{

XmlDocument doc = new XmlDocument();

// load employee.xml in XmlDocument

doc.Load("emp.xml");

// obtain a list of all employee element

XmlNodeList list = doc.GetElementsByTagName("employee");

foreach(XmlNode emp in list)

{

// obtain value of id attribute of the employee tag

string id = emp.Attributes["id"].Value;

// obtain value of salary subtag of the employee tag

string sal = emp["salary"].FirstChild.Value;

Console.WriteLine("{0}\t{1}",id,sal);

}

}

}

6.6. XML DOCUMENTS 95

The program addemp.cs takes informations from the command line (id, name, job,

salary) and makes a new entry in the file emp.xml.

// addemp.cs

using System;

using System.Xml;

class AddEmployee

{

public static void Main(string[] args)

{

XmlDocument doc = new XmlDocument();

doc.Load("emp.xml");

// create a new employee element and value of its attribute

XmlElement emp = doc.CreateElement("employee");

emp.SetAttribute("id",args[0]);

// create a name tag and st its value

XmlNode name = doc.CreateNode("element","name","");

name.InnerText = args[1];

// make name tag a subtag of newly created employee tag

emp.AppendChild(name);

XmlNode job = doc.CreateNode("element","job","");

job.InnerText = args[2];

emp.AppendChild(job);

XmlNode sal = doc.CreateNode("element","salary","");

sal.InnerText = args[3];

emp.AppendChild(sal);

// add the newly created employee tag to the root (employees) tag

doc.DocumentElement.AppendChild(emp);

// save the modified document

doc.Save("emp.xml");

}

}

We execute the program with (for example)

addemp 105 willi president 50000

No comments:

Post a Comment