270 likes | 384 Views
Applied Component-Based Software Engineering File I/O. CSE 668 / ECE 668 Prof. Roger Crawfis. Streams.
E N D
Applied Component-Based Software EngineeringFile I/O CSE 668 / ECE 668 Prof. Roger Crawfis
Streams • Streams are used anytime your program reads or writes a file, connects to another computer over a network, or generally does anything where it sends or receives bytes from one place to another.
Streams to read & write data • Let’s say you have a simple program – a form with an event handler that needs to read data from a file. You’ll use a Stream object to do it. • And if your program needs to write data out to the file, it can use another Stream object.
StreamWriter manages a FileStream • Use the StreamWriter’s constructor to open or create a file. StreamWriter writer = new StreamWriter(@"C:\toasterOven.txt", true); • Use the Write() and WriteLine() methods to write to the file. writer.WriteLine("The {0} is set to {1} degrees.", appliance, temp.ToString()); • Call the Close() method to release the file. writer.Close();
Make sure that you close streams! • Be sure to close every steam that you open, even if you are just reading a file. • Forgetting to close a stream is a big deal. • If a stream is not closed, the file will be locked, and other programs can’t use that file until you close your stream.
Data can go through many streams • You can chain streams. One stream can write to another stream, which writes to another stream… often ending with a network or file stream.
Built-in classes for Files & Directories • Like StreamWriter, the File class creates streams for you to work with files behind the scenes. • Likewise the Directory class lets you work with whole directories of files. • FileInfo instance for doing a lot of work with a particular file. • File class & static methods for a small number of actions.
File Support • Find out if it exists: Exists() method returns true or false. • Read from and write to the file: OpenRead() to get data, Create() or OpenWrite() to write to the file. • Append text to the file: AppendAllText() to append text to existing file. • Get information about the file: GetLastAccessTime() and GetLastWriteTime()
IDisposable for clean-up • Many .Net classes implement the interface called IDisposable. • This interface has only one member, the Dispose() method. • When a class implements IDisposable, that means there are important things that it needs to do in order to shut down. • Usually that is because it has allocated resources that it needs to release.
Using statements • Anytime that you use a stream, you should always declare it inside a using statement. • When you declare an object in a using block, that object’s Dispose() method is called automatically.
Using statements • Multiple using statements can be put together with one set of curly braces.
Applied Component-Based Software Engineering Garbage Collection CSE 668 / ECE 668 Prof. Roger Crawfis
Garbage Collection & Finalizers • When the last reference to an object is gone – there are no references to the object remaining – the object is ready to be garbage collected. • But we do not know when exactly that will happen. The .Net framework controls garbage collection, so it may be a few seconds or even minutes that the object still lives on in memory. • When the garbage collector runs again, it sees that it is a dead object – has no references – calls the finalizer and the object is removed from the heap.
Suggesting Garbage Collection • There is a method that allows you to suggest that garbage collection is run: GC.Collect(); • However that is all that it does… suggest. • Generally speaking, it is recommended that you do not do this.
Dispose() vs. Finalizers • Dispose() runs whenever an object that is created in a using statement is set to null or looses all of it’s references. • If you don’t use a using statement, then Dispose() is not called unless you call it directly. • Finalizers run automatically when garbage collection occurs.
Finalizers and the IDisposable interface Just because you implement IDisposable does not mean that your Dispose() method will get called. If a using statement is not used and the method is not called directly, then it will not run. The finalizercan call Dispose. This is ok, only if the Dispose() method does not depend on other object. The best way to avoid this issue is to always use a using statement when you use an IDisposable object.
Tracing Garbage Collectors • Initialize three sets for GC cycle bookkeeping • Initialize black set to empty • Initialize grey set to roots (active variables such as statically allocated and global objects, local variables on stack, variables in the registers) • Initialize white set to contain all other objects • Repeatedly attempt to detect/mark reachable objects • Pick an object from the grey set (until there are no more) • Move all the white objects reachable within one reference pointer deep from selected object to the grey set • Move the selected object from the grey set to the black set • Now reclaim/sweep storage space • White set contains left over objects that are NOT reachable
GC Variations on Mark and Sweep • Copying • Moving/non-moving GC (change/move address of objects in memory) • Incremental • Interleaved (incremental) or parallel (concurrent) or stop-the-world • Conservative • Identification of pointers (precise, conservative, partly conservative) • Generational • Collect in younger/newer generation
Garbage Collection in .NET • The CLR has a three generation based system. The theory is: • The newer an object is, the shorter its lifetime will be. • The older an object is, the longer its lifetime will be. • Collecting a portion of the heap is faster than collecting the whole heap. If it existed last time and was not garbage, chances are it is still not garbage.
Garbage Collection in .NET • Generation 0 has all of the newly created objects. • When it’s buffer is full, garbage collection happens. • Anything not garbage is promoted to Generation 1. • Tests before 2006 indicated the a generation 0 garbage collection took less than 1 millisecond. • Generation 1 and 2 occur along with generation 0 when the CLR determines that their sizes have gotten too large. • Special handling of very large memory allocations.