/// <summary> /// Create a new, blank, compound file. /// </summary> /// <param name="cfsVersion">Use a specific Compound File Version to set 512 or 4096 bytes sectors</param> /// <param name="sectorRecycle">If true, recycle unused sectors</param> /// <example> /// <code> /// /// byte[] b = new byte[10000]; /// for (int i = 0; i < 10000; i++) /// { /// b[i % 120] = (byte)i; /// } /// /// CompoundFile cf = new CompoundFile(CFSVersion.Ver_4, true, true); /// CFStream myStream = cf.RootStorage.AddStream("MyStream"); /// /// Assert.IsNotNull(myStream); /// myStream.SetData(b); /// cf.Save("MyCompoundFile.cfs"); /// cf.Close(); /// /// </code> /// </example> /// <remarks> /// Sector recycling reduces data writing performances but avoids space wasting in scenarios with frequently /// data manipulation of the same streams. The new compound file is open in Update mode. /// </remarks> public CompoundFile(CFSVersion cfsVersion, bool sectorRecycle) { _header = new Header((ushort) cfsVersion); _sectorRecycle = sectorRecycle; _difatSectorFATEntriesCount = (GetSectorSize()/4) - 1; _fatSectorEntriesCount = (GetSectorSize()/4); //Root -- RootStorage = new CFStorage(this); RootStorage.DirEntry.SetEntryName("Root Entry"); RootStorage.DirEntry.StgType = StgType.StgRoot; }
/// <summary> /// Load compound file from an existing stream. /// </summary> /// <param name="stream">Stream to load compound file from</param> private void Load(Stream stream) { try { _header = new Header(); _directoryEntries = new List<IDirectoryEntry>(); SourceStream = stream; _header.Read(stream); var numberOfSectors = Ceiling(((stream.Length - GetSectorSize())/(double) GetSectorSize())); if (stream.Length > 0x7FFFFF0) TransactionLockAllocated = true; _sectors = new SectorCollection(); for (var i = 0; i < numberOfSectors; i++) _sectors.Add(null); LoadDirectories(); RootStorage = new CFStorage(this, _directoryEntries[0]); } catch (Exception) { if (stream != null) stream.Close(); throw; } }
/// <summary> /// Create a blank, version 3 compound file. /// Sector recycle is turned off to achieve the best reading/writing /// performance in most common scenarios. /// </summary> /// <example> /// <code> /// /// byte[] b = new byte[10000]; /// for (int i = 0; i < 10000; i++) /// { /// b[i % 120] = (byte)i; /// } /// /// CompoundFile cf = new CompoundFile(); /// CFStream myStream = cf.RootStorage.AddStream("MyStream"); /// /// Assert.IsNotNull(myStream); /// myStream.SetData(b); /// cf.Save("MyCompoundFile.cfs"); /// cf.Close(); /// /// </code> /// </example> public CompoundFile() { _header = new Header(); _sectorRecycle = false; _difatSectorFATEntriesCount = (GetSectorSize()/4) - 1; _fatSectorEntriesCount = (GetSectorSize()/4); //Root -- RootStorage = new CFStorage(this); RootStorage.DirEntry.SetEntryName("Root Entry"); RootStorage.DirEntry.StgType = StgType.StgRoot; }
/// <summary> /// When called from user code, release all resources, otherwise, in the case runtime called it, /// only unmanagd resources are released. /// </summary> /// <param name="disposing">If true, method has been called from User code, if false it's been called from .net runtime</param> protected virtual void Dispose(bool disposing) { try { if (!IsClosed) { lock (_lockObject) { if (disposing) { // Call from user code... if (_sectors != null) { _sectors.Clear(); _sectors = null; } RootStorage = null; // Some problem releasing resources... _header = null; _directoryEntries.Clear(); _directoryEntries = null; _lockObject = null; _buffer = null; } if (SourceStream != null) SourceStream.Close(); } } } finally { IsClosed = true; } }