/// <summary>
        /// Return the MD5 of the whole item data
        /// </summary>
        /// <returns></returns>
        public string MD5()
        {
            if (CompleteDataStream != null)
            {
                return(CompleteDataStream.MD5());
            }
            else
            {
                lock (dataLocker)
                {
                    using (System.Security.Cryptography.HashAlgorithm md5 = System.Security.Cryptography.MD5.Create())
                    {
                        byte[] chunkBytes;
                        for (int i = 0; i < ChunkDataStreams.Length; i++)
                        {
                            chunkBytes = ChunkDataStreams[i].ToArray();

                            if (i < ChunkDataStreams.Length - 1)
                            {
                                md5.TransformBlock(chunkBytes, 0, chunkBytes.Length, chunkBytes, 0);
                            }
                            else
                            {
                                md5.TransformFinalBlock(chunkBytes, 0, chunkBytes.Length);
                            }
                        }

                        return(BitConverter.ToString(md5.Hash).Replace("-", ""));
                    }
                }
            }
        }
 /// <summary>
 /// Disposes the internal stream. If <see cref="StreamTools.ThreadSafeStream.DiposeInnerStreamOnDispose"/> is false, forceDispose
 /// must be true to dispose of the internal stream.
 /// </summary>
 /// <param name="forceDispose">If true the internal stream will be disposed regardless of <see cref="StreamTools.ThreadSafeStream.DiposeInnerStreamOnDispose"/> value.</param>
 public void Dispose(bool forceDispose)
 {
     if (CompleteDataStream != null)
     {
         CompleteDataStream.Dispose(forceDispose);
     }
     else
     {
         for (int i = 0; i < ChunkDataStreams.Length; i++)
         {
             ChunkDataStreams[i].Dispose(forceDispose);
         }
     }
 }
 /// <summary>
 /// Copies data specified by start and length properties from internal stream to the provided stream.
 /// </summary>
 /// <param name="destinationStream">The destination stream for the item data</param>
 public void CopyTo(Stream destinationStream)
 {
     lock (dataLocker)
     {
         if (CompleteDataStream != null)
         {
             CompleteDataStream.CopyTo(destinationStream, 0, CompleteDataStream.Length, 8192, double.MaxValue, int.MaxValue);
         }
         else
         {
             for (int i = 0; i < ChunkDataStreams.Length; i++)
             {
                 ChunkDataStreams[i].CopyTo(destinationStream, 0, ChunkDataStreams[i].Length, 8192, double.MaxValue, int.MaxValue);
             }
         }
     }
 }
        /// <summary>
        /// Writes the provided buffer to the data starting at the provided position within the item data
        /// </summary>
        /// <param name="chunkIndex"></param>
        /// <param name="chunkData"></param>
        public void Write(int chunkIndex, byte[] chunkData)
        {
            if (chunkIndex < 0)
            {
                throw new ArgumentException("ChunkIndex cannot be less than 0.");
            }
            if (chunkIndex >= ChunkPositionLengthDict.Count)
            {
                throw new ArgumentException("ChunkIndex was greater than the number of chunks");
            }

            if (CompleteDataStream != null)
            {
                long startPosition = ChunkPositionLengthDict[chunkIndex].Position;

                CompleteDataStream.Write(chunkData, startPosition);
            }
            else
            {
                ChunkDataStreams[chunkIndex].Write(chunkData, 0);
            }
        }
        /// <summary>
        /// Return the MD5 of the specified chunk
        /// </summary>
        /// <param name="chunkIndex"></param>
        /// <returns></returns>
        public string MD5(int chunkIndex)
        {
            if (chunkIndex < 0)
            {
                throw new ArgumentException("ChunkIndex cannot be less than 0.");
            }
            if (chunkIndex >= ChunkPositionLengthDict.Count)
            {
                throw new ArgumentException("ChunkIndex was greater than the number of chunks");
            }

            if (CompleteDataStream != null)
            {
                long start  = ChunkPositionLengthDict[chunkIndex].Position;
                int  length = ChunkPositionLengthDict[chunkIndex].Length;

                return(CompleteDataStream.MD5(start, length));
            }
            else
            {
                return(ChunkDataStreams[chunkIndex].MD5());
            }
        }