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;
            }
        }
Esempio n. 5
0
        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;
            }
        }
Esempio n. 6
0
        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;
            }
        }