/// <summary> /// /// </summary> /// <param name="fileSystem"></param> /// <param name="exportingFolderPath"></param> /// <param name="virtualDestinationFolder"></param> /// <param name="taskToken"></param> /// <returns></returns> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="CannotGetImportedFolderStructureException"></exception> /// <exception cref="FolderNotFoundException"></exception> internal static ReadOnlyCollection <FileSystemTaskResult> ImportFolderFromRealFileSystem( this VirtualFileSystem fileSystem, string exportingFolderPath, string virtualDestinationFolder, IFileSystemCancellableTaskToken taskToken) { if (fileSystem == null) { throw new ArgumentNullException("fileSystem"); } MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(exportingFolderPath, "exportingFolderPath"); MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(virtualDestinationFolder, "virtualDestinationFolder"); FolderAddressable folderAddressable = CreateFileSystemObjectStructureFromFolder(exportingFolderPath); int totalNumberOfFilesToTraverse = folderAddressable.GetTotalFileCount(); // Note: можно уменьшить связность классов, передав сюда через интерфейс фабрику, которая уж знает, как сделать нужного Visitor-а. ImportingAddressableObjectVisitor visitor = new ImportingAddressableObjectVisitor(fileSystem, exportingFolderPath, virtualDestinationFolder, new RealFileContentsBufferFactory(), taskToken, totalNumberOfFilesToTraverse); if (!fileSystem.FolderExists(virtualDestinationFolder)) { throw new FolderNotFoundException("Не удалось найти папку \"{0}\", в которую следует произвести копирование/импорт.".FormatWith(virtualDestinationFolder)); } folderAddressable.Accept(visitor); var results = visitor.GetResult(); return(results); }
public ImportingAddressableObjectVisitor( VirtualFileSystem targetFileSystem, string sourceFolderPath, string destinationFolder, IFileContentsBufferFactory fileContentsBufferFactory, IFileSystemCancellableTaskToken taskToken, int totalNumberOfFilesToVisit) { if (targetFileSystem == null) { throw new ArgumentNullException("targetFileSystem"); } if (sourceFolderPath == null) { throw new ArgumentNullException("sourceFolderPath"); } if (destinationFolder == null) { throw new ArgumentNullException("destinationFolder"); } if (fileContentsBufferFactory == null) { throw new ArgumentNullException("fileContentsBufferFactory"); } if (taskToken == null) { throw new ArgumentNullException("taskToken"); } _targetFileSystem = targetFileSystem; _sourceFolderPath = sourceFolderPath; _destinationFolder = destinationFolder; _fileContentsBufferFactory = fileContentsBufferFactory; _taskToken = taskToken; _totalNumberOfFilesToVisit = totalNumberOfFilesToVisit; }
/// <exception cref="ArgumentNullException"></exception> /// <exception cref="FileNotFoundException"></exception> /// <exception cref="FileLockedException"></exception> /// <exception cref="ObjectDisposedException"></exception> /// <exception cref="InvalidPathException"></exception> /// <exception cref="FolderNotFoundException"></exception> /// <exception cref="FileAlreadyExistsException"></exception> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="MaximumFileCountReachedException"></exception> /// <exception cref="MaximumFileSizeReachedException"></exception> /// <exception cref="TaskCancelledException"></exception> private void CopyFileContents(IFileSystemCancellableTaskToken taskToken, string fullPathForFileToBeCopied, string newPathThatWillPointToTheCopyOfFile) { using (var readingStream = this.OpenFileForReading(fullPathForFileToBeCopied)) { double totalNumberOfBytesToWrite = readingStream.Length; int percentage = 0; double numberOfBytesWritten = 0; var buffer = new byte[FileCopyingBufferSizeInBytes]; using (var writingStream = this.CreateAndOpenFileForWriting(newPathThatWillPointToTheCopyOfFile)) { int numberOfBytesRead; while ((numberOfBytesRead = readingStream.Read(buffer, 0, FileCopyingBufferSizeInBytes)) != 0) { writingStream.Write(buffer, 0, numberOfBytesRead); numberOfBytesWritten += numberOfBytesRead; int newPercentage = (int)((numberOfBytesWritten / totalNumberOfBytesToWrite) * 100); if (newPercentage != percentage) { percentage = newPercentage; taskToken.ReportProgressChange(newPercentage); } if (taskToken.HasBeenCancelled) { throw new TaskCancelledException("Задача снята"); } } } } }
/// <summary> /// Копирует указанный файл. /// </summary> /// <param name="fullPathForFileToBeCopied">Полный путь (от корня), указывающий файл, который следует скопировать.</param> /// <param name="newPathThatWillPointToTheCopyOfFile">Полный путь (от корня), указывающий, где будет находиться и как называться копия файла.</param> /// <param name="taskToken"></param> /// <returns>Описание копии файла.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="FileNotFoundException"></exception> /// <exception cref="FileLockedException"></exception> /// <exception cref="ObjectDisposedException"></exception> /// <exception cref="InvalidPathException"></exception> /// <exception cref="FolderNotFoundException"></exception> /// <exception cref="FileAlreadyExistsException"></exception> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="MaximumFileCountReachedException"></exception> /// <exception cref="TaskCancelledException"></exception> internal FileInfo CopyFile(string fullPathForFileToBeCopied, string newPathThatWillPointToTheCopyOfFile, IFileSystemCancellableTaskToken taskToken) { if (taskToken == null) { throw new ArgumentNullException("taskToken"); } MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFileToBeCopied, "fullPathForFileToBeCopied"); MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newPathThatWillPointToTheCopyOfFile, "newPathThatWillPointToTheCopyOfFile"); if (_namesComparer.Equals(fullPathForFileToBeCopied, newPathThatWillPointToTheCopyOfFile)) { return (new FileInfo(_nodeResolver.ResolveFileNodeByPath(newPathThatWillPointToTheCopyOfFile).ResolvedNode, newPathThatWillPointToTheCopyOfFile)); } lock (_operationExecutionCriticalSection) { ThrowIfDisposed(); // так себе проверка на этот раз. } // Note: не смотрю, хватит ли там места. Хотя отрицательный ответ на такой вопрос мог бы стать поводом, чтобы ничего не копировать. try { CopyFileContents(taskToken, fullPathForFileToBeCopied, newPathThatWillPointToTheCopyOfFile); return (new FileInfo(_nodeResolver.ResolveFileNodeByPath(newPathThatWillPointToTheCopyOfFile).ResolvedNode, newPathThatWillPointToTheCopyOfFile)); } catch (Exception) { try { this.DeleteFile(newPathThatWillPointToTheCopyOfFile); } catch (InvalidPathException) { } catch (ObjectDisposedException) { throw new ObjectDisposedException("Работа с файловой системой была вами завершена принудительным вызовом метода Dispose() - до того, как был докопирован файл. Рекомендуется удалить следующий файл при очередном запуске системы (простите - в текущей версии ничего более удобного не сделано): \"{0}\"".FormatWith(newPathThatWillPointToTheCopyOfFile)); } catch (FileNotFoundException) { } throw; } }
/// <exception cref="InvalidPathException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="FolderNotFoundException"></exception> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="MaximumFolderCountReachedException"></exception> /// <exception cref="ObjectDisposedException"></exception> internal ReadOnlyCollection <FileSystemTaskResult> CopyFolder(string fullPathForFolderToCopy, string destinationPathForFolderAndItsContents, IFileSystemCancellableTaskToken taskToken) { if (taskToken == null) { throw new ArgumentNullException("taskToken"); } MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFolderToCopy, "fullPathForFolderToCopy"); MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(destinationPathForFolderAndItsContents, "destinationPathForFolderAndItsContents"); // TODO: выделить общее у копированиея папок и импорта - там много. var allFilesToBeCopied = new List <FileInfo>(); CreateFoldersNeededToCopy(fullPathForFolderToCopy, destinationPathForFolderAndItsContents, allFilesToBeCopied); var copyTaskResults = new List <FileSystemTaskResult>(); int filesCopied = 0; int percentage = 0; foreach (FileInfo fileInfo in allFilesToBeCopied) { try { if (taskToken.HasBeenCancelled) { copyTaskResults.Add(new FileTaskResult(fileInfo.ToFileAddressable(), null, "Задача снята.")); } else { string relativePathToFile = _pathBuilder.GetRelativePath(fullPathForFolderToCopy, fileInfo.FullPath); string destinationPath = this.PathBuilder.CombinePaths(destinationPathForFolderAndItsContents, relativePathToFile); var tokenWrapper = new TaskTokenPartialWrapper(taskToken); var copiedFileInfo = this.CopyFile(fileInfo.FullPath, destinationPath, tokenWrapper); copyTaskResults.Add(new FileTaskResult(fileInfo.ToFileAddressable(), copiedFileInfo.ToFileAddressable(), String.Empty)); } } catch (TaskCancelledException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (FileNotFoundException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (FileLockedException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (ObjectDisposedException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (InvalidPathException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (FolderNotFoundException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (FileAlreadyExistsException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (InsufficientSpaceException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } catch (MaximumFileCountReachedException exception) { copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception)); } finally { // Note: дурацкая часть по высчету прогресса везде общая. Надо выносить. filesCopied++; int newPercentage = (filesCopied * 100) / allFilesToBeCopied.Count; if (newPercentage != percentage) { percentage = newPercentage; taskToken.ReportProgressChange(newPercentage); } } } return(copyTaskResults.AsReadOnly()); }
public TaskTokenPartialWrapper(IFileSystemCancellableTaskToken token) { _token = token; }