static TeaFile <T> Append(Stream stream, bool ownsStream, Stream headerReadStream, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All) { var tf = new TeaFile <T>(); try { TeaFileDescription description; tf.core = new TeaFileCore(stream, ownsStream); // A file opened for appending, cannot be read. Therefore we create a second file, read it and assign its description to the current TeaFile<> instance. using (var tfheader = OpenRead(headerReadStream, false, elementsToValidate)) // we pass headerStream ownership to tfheader, so it will be closed after header reaeding. { description = tfheader.Description; if (!tfheader.core.CanAppend) { throw new IOException("Cannot append to file because it has preallocated space between the end of the item area and the end of the file."); } tf.core.Assign(tfheader.ItemAreaStart, tfheader.core.ItemAreaEndMarker); } // if the stream is a filestream that was opened in FileMode.Append, this call is redundant. // this line is here for the allowed case were the stream and headerstream point to the same stream. tf.SetFilePointerToEnd(); tf.core.Description = description; tf.buffer = new SafeBuffer <T>(stream); return(tf); } catch (Exception) { tf.Dispose(); throw; } }
static TeaFile <T> OpenRead(Stream stream, bool ownsStream, ItemDescriptionElements elementsToValidate) { var tf = new TeaFile <T>(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.buffer = new SafeBuffer <T>(stream); tf.core.ReadHeader(); // reflecting the current type incurs some cost, so we do it only if we are asked to consider // current item layout to check it against to layout described in the file ItemDescription accessorDescription = null; if (elementsToValidate != ItemDescriptionElements.None) { accessorDescription = ItemDescription.FromAnalysis <T>(); } tf.core.IsAccessibleWith(accessorDescription, elementsToValidate); return(tf); } catch (Exception) { tf.Dispose(); throw; } }
/// <summary> /// Creates a TeaFile, using the specified stream as the underlying storage media. /// </summary> /// <param name="stream">The stream.</param> /// <param name="ownsStream">If true, the instance returned owns the stream, such that disposing the returned instance also disposes <paramref name="stream"/>.</param> /// <param name="contentDescription">The content description.</param> /// <param name="nameValues">The name values.</param> /// <param name="includeItemDescription">if set to <c>true</c> [include item description].</param> /// <returns></returns> /// <remarks> /// Instead of creating a new <see cref="FileStream"/>, this method takes the <see cref="Stream"/> passed. This provides /// more control over the stream, like setting specific <see cref="FileShare"/> attributes. It also allows usage of /// alternative storage medias like <see cref="MemoryStream"/>. /// </remarks> public static TeaFile <T> Create(Stream stream, bool ownsStream, string contentDescription = null, NameValueCollection nameValues = null, bool includeItemDescription = true) { if (stream == null) { throw new ArgumentNullException("stream"); } var tf = new TeaFile <T>(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.buffer = new SafeBuffer <T>(stream); if (includeItemDescription) { tf.Description.ItemDescription = ItemDescription.FromAnalysis <T>(); } tf.Description.ContentDescription = contentDescription; tf.Description.NameValues = nameValues; tf.Description.Timescale = Time.Scale; // The tf.core.WriteHeader(); tf.Flush(); return(tf); } catch (Exception) { tf.Dispose(); throw; } }
static TeaFile <T> OpenWrite(Stream stream, bool ownsStream, ItemDescriptionElements elementsToValidate) { var tf = new TeaFile <T>(); try { tf.buffer = new SafeBuffer <T>(stream); tf.core = new TeaFileCore(stream, ownsStream); tf.core.ReadHeader(); tf.core.IsAccessibleWith(ItemDescription.FromAnalysis <T>(), elementsToValidate); // filepointer is at begin of item area. finally, the user might want to read. // using filepointer is essential here. // check the item api to allow this. return(tf); } catch (Exception) { tf.Dispose(); throw; } }
static TeaFile OpenRead(Stream stream, bool ownsStream) { var tf = new TeaFile(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.core.ReadHeader(); // protect against empty Item structs if (tf.Description.ItemDescription != null) { if (!tf.Description.ItemDescription.Fields.Any()) { throw new ItemException("Cannot read this file because the item has no fields according to its item description in the file."); } } tf.reader = new BinaryReader(tf.core.Stream); if (tf.Description.ItemDescription != null) { // A field might occupy equal or more bytes than the size of its type due to padding bytes // inserted between the fields or between items in the ItemArray. The paddingBytes array // holds the number of bytes that will be read after reading a field in order to set the // file pointer to the next field. tf.fieldSpacings = tf.GetFieldSpacings(); } return(tf); } catch { tf.Dispose(); // since we will not hand out the disposable TeaFile instance, // we must close the filestream if header reading failed! throw; } }
static TeaFile OpenRead(Stream stream, bool ownsStream) { var tf = new TeaFile(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.core.ReadHeader(); // protect against empty Item structs if (tf.Description.ItemDescription != null) { if (!tf.Description.ItemDescription.Fields.Any()) { throw new ItemException("Cannot read this file because the item has no fields according to its item description in the file."); } } tf.reader = new BinaryReader(tf.core.Stream); if (tf.Description.ItemDescription != null) { // A field might occupy equal or more bytes than the size of its type due to padding bytes // inserted between the fields or between items in the ItemArray. The paddingBytes array // holds the number of bytes that will be read after reading a field in order to set the // file pointer to the next field. tf.fieldSpacings = tf.GetFieldSpacings(); } return tf; } catch { tf.Dispose(); // since we will not hand out the disposable TeaFile instance, // we must close the filestream if header reading failed! throw; } }