/// <summary>
        ///         copies this file into the target directory with a given name.
        /// </summary>
        /// <param name="targetDirectory">the target directory this file should be copied to</param>
        /// <param name="newName">the new name the copied file should take after copying.</param>
        /// <returns>the created copy.</returns>
        public override VirtualItem Copy(VirtualDirectory targetDirectory, string newName)
        {
            const int COPY_CHUNK_SIZE = 2048;

                        if (!ValidName(newName))
                        {
                                throw new ArgumentException("newName invalid");
                        }

                        if (targetDirectory == null)
                        {
                                throw new ArgumentException("targetDirectory must not be null");
                        }

                        if (targetDirectory.ReadAllItems().Any(item => item.Name.Equals(newName)))
                        {
                                throw new ItemNameInUseException(newName);
                        }

                        VirtualFile fileCopy = targetDirectory.AddFile(newName);

                        FileStream fromStream = GetFileStream();
                        FileStream toStream = fileCopy.GetFileStream();

                        ContainerFile.ChangeFileSize(fileCopy.FileNumber, fromStream.Length);

                        long fromStreamLength = fromStream.Length;

                        while (fromStream.Position < fromStreamLength)
                        {
                                long remainingData = fromStreamLength - fromStream.Position;

                                long amountToCopy = COPY_CHUNK_SIZE < remainingData ? COPY_CHUNK_SIZE : remainingData;

                                toStream.Write(fromStream.Read(amountToCopy));
                        }

                        return fileCopy;
        }
        private VirtualDirectory CopyInternal(VirtualDirectory targetDirectory, string newName, HashSet<uint> copies)
        {
            if (copies.Contains(FileNumber)) return null;

                        VirtualItem[] items = ReadAllItems().ToArray();

                        int copyNumber = 0;
                        string baseName = newName;
                        VirtualItem[] targetItems = targetDirectory.ReadAllItems().ToArray();
                        while (targetItems.Any(item => item.Name.Equals(baseName)))
                        {
                                baseName = newName + ++copyNumber;
                        }

                        VirtualDirectory directoryCopy = targetDirectory.AddDirectory(baseName);

                        copies.Add(directoryCopy.FileNumber);

                        foreach (VirtualDirectory directory in items.OfType<VirtualDirectory>())
                        {
                                directory.CopyInternal(directoryCopy, directory.Name, copies);
                        }

                        foreach (VirtualFile file in items.OfType<VirtualFile>())
                        {
                                file.Copy(directoryCopy, file.Name);
                        }

                        return directoryCopy;
        }