zoukankan      html  css  js  c++  java
  • netcore3.0 IFileProvider 文件系统

    Nuget包:以Microsoft.Extensins.FileProviders开头的包中

    Github地址:https://github.com/dotnet/extensions/tree/master/src/FileProviders

     

     一、PhysicalFileProvider

     /// <summary>
        /// Represents a file on a physical filesystem
        /// </summary>
        public class PhysicalFileInfo : IFileInfo
        {
            private readonly FileInfo _info;
    
            /// <summary>
            /// Initializes an instance of <see cref="PhysicalFileInfo"/> that wraps an instance of <see cref="System.IO.FileInfo"/>
            /// </summary>
            /// <param name="info">The <see cref="System.IO.FileInfo"/></param>
            public PhysicalFileInfo(FileInfo info)
            {
                _info = info;
            }
    
            /// <inheritdoc />
            public bool Exists => _info.Exists;
    
            /// <inheritdoc />
            public long Length => _info.Length;
    
            /// <inheritdoc />
            public string PhysicalPath => _info.FullName;
    
            /// <inheritdoc />
            public string Name => _info.Name;
    
            /// <inheritdoc />
            public DateTimeOffset LastModified => _info.LastWriteTimeUtc;
    
            /// <summary>
            /// Always false.
            /// </summary>
            public bool IsDirectory => false;
    
            /// <inheritdoc />
            public Stream CreateReadStream()
            {
                // We are setting buffer size to 1 to prevent FileStream from allocating it's internal buffer
                // 0 causes constructor to throw
                var bufferSize = 1;
                return new FileStream(
                    PhysicalPath,
                    FileMode.Open,
                    FileAccess.Read,
                    FileShare.ReadWrite,
                    bufferSize,
                    FileOptions.Asynchronous | FileOptions.SequentialScan);
            }
        }
    /// <summary>
        /// Looks up files using the on-disk file system
        /// </summary>
        /// <remarks>
        /// When the environment variable "DOTNET_USE_POLLING_FILE_WATCHER" is set to "1" or "true", calls to
        /// <see cref="Watch(string)" /> will use <see cref="PollingFileChangeToken" />.
        /// </remarks>
        public class PhysicalFileProvider : IFileProvider, IDisposable
        {
            private const string PollingEnvironmentKey = "DOTNET_USE_POLLING_FILE_WATCHER";
            private static readonly char[] _pathSeparators = new[]
                {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
    
            private readonly ExclusionFilters _filters;
    
            private readonly Func<PhysicalFilesWatcher> _fileWatcherFactory;
            private PhysicalFilesWatcher _fileWatcher;
            private bool _fileWatcherInitialized;
            private object _fileWatcherLock = new object();
    
            private bool? _usePollingFileWatcher;
            private bool? _useActivePolling;
    
            /// <summary>
            /// Initializes a new instance of a PhysicalFileProvider at the given root directory.
            /// </summary>
            /// <param name="root">The root directory. This should be an absolute path.</param>
            public PhysicalFileProvider(string root)
                : this(root, ExclusionFilters.Sensitive)
            {
            }
    
            /// <summary>
            /// Initializes a new instance of a PhysicalFileProvider at the given root directory.
            /// </summary>
            /// <param name="root">The root directory. This should be an absolute path.</param>
            /// <param name="filters">Specifies which files or directories are excluded.</param>
            public PhysicalFileProvider(string root, ExclusionFilters filters)
            {
                if (!Path.IsPathRooted(root))
                {
                    throw new ArgumentException("The path must be absolute.", nameof(root));
                }
    
                var fullRoot = Path.GetFullPath(root);
                // When we do matches in GetFullPath, we want to only match full directory names.
                Root = PathUtils.EnsureTrailingSlash(fullRoot);
                if (!Directory.Exists(Root))
                {
                    throw new DirectoryNotFoundException(Root);
                }
    
                _filters = filters;
                _fileWatcherFactory = () => CreateFileWatcher();
            }
    
            /// <summary>
            /// Gets or sets a value that determines if this instance of <see cref="PhysicalFileProvider"/>
            /// uses polling to determine file changes.
            /// <para>
            /// By default, <see cref="PhysicalFileProvider"/>  uses <see cref="FileSystemWatcher"/> to listen to file change events
            /// for <see cref="Watch(string)"/>. <see cref="FileSystemWatcher"/> is ineffective in some scenarios such as mounted drives.
            /// Polling is required to effectively watch for file changes.
            /// </para>
            /// <seealso cref="UseActivePolling"/>.
            /// </summary>
            /// <value>
            /// The default value of this property is determined by the value of environment variable named <c>DOTNET_USE_POLLING_FILE_WATCHER</c>.
            /// When <c>true</c> or <c>1</c>, this property defaults to <c>true</c>; otherwise false.
            /// </value>
            public bool UsePollingFileWatcher
            {
                get
                {
                    if (_fileWatcher != null)
                    {
                        throw new InvalidOperationException($"Cannot modify {nameof(UsePollingFileWatcher)} once file watcher has been initialized.");
                    }
    
                    if (_usePollingFileWatcher == null)
                    {
                        ReadPollingEnvironmentVariables();
                    }
    
                    return _usePollingFileWatcher.Value;
                }
                set => _usePollingFileWatcher = value;
            }
    
            /// <summary>
            /// Gets or sets a value that determines if this instance of <see cref="PhysicalFileProvider"/>
            /// actively polls for file changes.
            /// <para>
            /// When <see langword="true"/>, <see cref="IChangeToken"/> returned by <see cref="Watch(string)"/> will actively poll for file changes
            /// (<see cref="IChangeToken.ActiveChangeCallbacks"/> will be <see langword="true"/>) instead of being passive.
            /// </para>
            /// <para>
            /// This property is only effective when <see cref="UsePollingFileWatcher"/> is set.
            /// </para>
            /// </summary>
            /// <value>
            /// The default value of this property is determined by the value of environment variable named <c>DOTNET_USE_POLLING_FILE_WATCHER</c>.
            /// When <c>true</c> or <c>1</c>, this property defaults to <c>true</c>; otherwise false.
            /// </value>
            public bool UseActivePolling
            {
                get
                {
                    if (_useActivePolling == null)
                    {
                        ReadPollingEnvironmentVariables();
                    }
    
                    return _useActivePolling.Value;
                }
    
                set => _useActivePolling = value;
            }
    
            internal PhysicalFilesWatcher FileWatcher
            {
                get
                {
                    return LazyInitializer.EnsureInitialized(
                        ref _fileWatcher,
                        ref _fileWatcherInitialized,
                        ref _fileWatcherLock,
                        _fileWatcherFactory);
                }
                set
                {
                    Debug.Assert(!_fileWatcherInitialized);
    
                    _fileWatcherInitialized = true;
                    _fileWatcher = value;
                }
            }
    
            internal PhysicalFilesWatcher CreateFileWatcher()
            {
                var root = PathUtils.EnsureTrailingSlash(Path.GetFullPath(Root));
                return new PhysicalFilesWatcher(root, new FileSystemWatcher(root), UsePollingFileWatcher, _filters)
                {
                    UseActivePolling = UseActivePolling,
                };
            }
    
            private void ReadPollingEnvironmentVariables()
            {
                var environmentValue = Environment.GetEnvironmentVariable(PollingEnvironmentKey);
                var pollForChanges = string.Equals(environmentValue, "1", StringComparison.Ordinal) ||
                    string.Equals(environmentValue, "true", StringComparison.OrdinalIgnoreCase);
    
                _usePollingFileWatcher = pollForChanges;
                _useActivePolling = pollForChanges;
            }
    
            /// <summary>
            /// Disposes the provider. Change tokens may not trigger after the provider is disposed.
            /// </summary>
            public void Dispose() => Dispose(true);
    
            /// <summary>
            /// Disposes the provider.
            /// </summary>
            /// <param name="disposing"><c>true</c> is invoked from <see cref="IDisposable.Dispose"/>.</param>
            protected virtual void Dispose(bool disposing)
            {
                _fileWatcher?.Dispose();
            }
    
            /// <summary>
            /// Destructor for <see cref="PhysicalFileProvider"/>.
            /// </summary>
            ~PhysicalFileProvider() => Dispose(false);
    
            /// <summary>
            /// The root directory for this instance.
            /// </summary>
            public string Root { get; }
    
            private string GetFullPath(string path)
            {
                if (PathUtils.PathNavigatesAboveRoot(path))
                {
                    return null;
                }
    
                string fullPath;
                try
                {
                    fullPath = Path.GetFullPath(Path.Combine(Root, path));
                }
                catch
                {
                    return null;
                }
    
                if (!IsUnderneathRoot(fullPath))
                {
                    return null;
                }
    
                return fullPath;
            }
    
            private bool IsUnderneathRoot(string fullPath)
            {
                return fullPath.StartsWith(Root, StringComparison.OrdinalIgnoreCase);
            }
    
            /// <summary>
            /// Locate a file at the given path by directly mapping path segments to physical directories.
            /// </summary>
            /// <param name="subpath">A path under the root directory</param>
            /// <returns>The file information. Caller must check <see cref="IFileInfo.Exists"/> property. </returns>
            public IFileInfo GetFileInfo(string subpath)
            {
                if (string.IsNullOrEmpty(subpath) || PathUtils.HasInvalidPathChars(subpath))
                {
                    return new NotFoundFileInfo(subpath);
                }
    
                // Relative paths starting with leading slashes are okay
                subpath = subpath.TrimStart(_pathSeparators);
    
                // Absolute paths not permitted.
                if (Path.IsPathRooted(subpath))
                {
                    return new NotFoundFileInfo(subpath);
                }
    
                var fullPath = GetFullPath(subpath);
                if (fullPath == null)
                {
                    return new NotFoundFileInfo(subpath);
                }
    
                var fileInfo = new FileInfo(fullPath);
                if (FileSystemInfoHelper.IsExcluded(fileInfo, _filters))
                {
                    return new NotFoundFileInfo(subpath);
                }
    
                return new PhysicalFileInfo(fileInfo);
            }
    
            /// <summary>
            /// Enumerate a directory at the given path, if any.
            /// </summary>
            /// <param name="subpath">A path under the root directory. Leading slashes are ignored.</param>
            /// <returns>
            /// Contents of the directory. Caller must check <see cref="IDirectoryContents.Exists"/> property. <see cref="NotFoundDirectoryContents" /> if
            /// <paramref name="subpath" /> is absolute, if the directory does not exist, or <paramref name="subpath" /> has invalid
            /// characters.
            /// </returns>
            public IDirectoryContents GetDirectoryContents(string subpath)
            {
                try
                {
                    if (subpath == null || PathUtils.HasInvalidPathChars(subpath))
                    {
                        return NotFoundDirectoryContents.Singleton;
                    }
    
                    // Relative paths starting with leading slashes are okay
                    subpath = subpath.TrimStart(_pathSeparators);
    
                    // Absolute paths not permitted.
                    if (Path.IsPathRooted(subpath))
                    {
                        return NotFoundDirectoryContents.Singleton;
                    }
    
                    var fullPath = GetFullPath(subpath);
                    if (fullPath == null || !Directory.Exists(fullPath))
                    {
                        return NotFoundDirectoryContents.Singleton;
                    }
    
                    return new PhysicalDirectoryContents(fullPath, _filters);
                }
                catch (DirectoryNotFoundException)
                {
                }
                catch (IOException)
                {
                }
                return NotFoundDirectoryContents.Singleton;
            }
    
            /// <summary>
            ///     <para>Creates a <see cref="IChangeToken" /> for the specified <paramref name="filter" />.</para>
            ///     <para>Globbing patterns are interpreted by <seealso cref="Microsoft.Extensions.FileSystemGlobbing.Matcher" />.</para>
            /// </summary>
            /// <param name="filter">
            /// Filter string used to determine what files or folders to monitor. Example: **/*.cs, *.*,
            /// subFolder/**/*.cshtml.
            /// </param>
            /// <returns>
            /// An <see cref="IChangeToken" /> that is notified when a file matching <paramref name="filter" /> is added,
            /// modified or deleted. Returns a <see cref="NullChangeToken" /> if <paramref name="filter" /> has invalid filter
            /// characters or if <paramref name="filter" /> is an absolute path or outside the root directory specified in the
            /// constructor <seealso cref="PhysicalFileProvider(string)" />.
            /// </returns>
            public IChangeToken Watch(string filter)
            {
                if (filter == null || PathUtils.HasInvalidFilterChars(filter))
                {
                    return NullChangeToken.Singleton;
                }
    
                // Relative paths starting with leading slashes are okay
                filter = filter.TrimStart(_pathSeparators);
    
                return FileWatcher.CreateFileChangeToken(filter);
            }
        }

    可以看到PhysicalFileProvider的构造行数,需要传递两个参数,root目录和ExclusionFilters类型的filters(过滤一些文件)

    PhysicalFileProvider类的GetFileInfo会根据传递的文件名或子目录获取对应的FileInfo对象,并返回PhysicalFileInfo对象

    FileProvider的简单使用:

     在项目下创建如下目录结构

    class Program
        {
            static void Main(string[] args)
            {
    
                var fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "files"));
                var fileInfo = fileProvider.GetFileInfo("data.txt");
                using (var streamReader = new StreamReader(fileInfo.CreateReadStream()))
                {
                    var result = streamReader.ReadToEnd();
                    Console.WriteLine(result);
                }
                var contents = fileProvider.GetDirectoryContents("sub");
                foreach (var item in contents)
                {
                    Console.WriteLine(item.Name);
                }
    
    
                Console.Read();
    
            }
        }

    二、 ManifestEmbeddedFileProvider

      

    /// <summary>
        /// Represents a file embedded in an assembly.
        /// </summary>
        public class EmbeddedResourceFileInfo : IFileInfo
        {
            private readonly Assembly _assembly;
            private readonly string _resourcePath;
    
            private long? _length;
    
            /// <summary>
            /// Initializes a new instance of <see cref="EmbeddedFileProvider"/> for an assembly using <paramref name="resourcePath"/> as the base
            /// </summary>
            /// <param name="assembly">The assembly that contains the embedded resource</param>
            /// <param name="resourcePath">The path to the embedded resource</param>
            /// <param name="name">An arbitrary name for this instance</param>
            /// <param name="lastModified">The <see cref="DateTimeOffset" /> to use for <see cref="LastModified" /></param>
            public EmbeddedResourceFileInfo(
                Assembly assembly,
                string resourcePath,
                string name,
                DateTimeOffset lastModified)
            {
                _assembly = assembly;
                _resourcePath = resourcePath;
                Name = name;
                LastModified = lastModified;
            }
    
            /// <summary>
            /// Always true.
            /// </summary>
            public bool Exists => true;
    
            /// <summary>
            /// The length, in bytes, of the embedded resource
            /// </summary>
            public long Length
            {
                get
                {
                    if (!_length.HasValue)
                    {
                        using (var stream = _assembly.GetManifestResourceStream(_resourcePath))
                        {
                            _length = stream.Length;
                        }
                    }
                    return _length.Value;
                }
            }
    
            /// <summary>
            /// Always null.
            /// </summary>
            public string PhysicalPath => null;
    
            /// <summary>
            /// The name of embedded file
            /// </summary>
            public string Name { get; }
    
            /// <summary>
            /// The time, in UTC, when the <see cref="EmbeddedFileProvider"/> was created
            /// </summary>
            public DateTimeOffset LastModified { get; }
    
            /// <summary>
            /// Always false.
            /// </summary>
            public bool IsDirectory => false;
    
            /// <inheritdoc />
            public Stream CreateReadStream()
            {
                var stream = _assembly.GetManifestResourceStream(_resourcePath);
                if (!_length.HasValue)
                {
                    _length = stream.Length;
                }
    
                return stream;
            }
        }
    /// <summary>
        /// An embedded file provider that uses a manifest compiled in the assembly to
        /// reconstruct the original paths of the embedded files when they were embedded
        /// into the assembly.
        /// </summary>
        public class ManifestEmbeddedFileProvider : IFileProvider
        {
            private readonly DateTimeOffset _lastModified;
    
            /// <summary>
            /// Initializes a new instance of <see cref="ManifestEmbeddedFileProvider"/>.
            /// </summary>
            /// <param name="assembly">The assembly containing the embedded files.</param>
            public ManifestEmbeddedFileProvider(Assembly assembly)
                : this(assembly, ManifestParser.Parse(assembly), ResolveLastModified(assembly)) { }
    
            /// <summary>
            /// Initializes a new instance of <see cref="ManifestEmbeddedFileProvider"/>.
            /// </summary>
            /// <param name="assembly">The assembly containing the embedded files.</param>
            /// <param name="root">The relative path from the root of the manifest to use as root for the provider.</param>
            public ManifestEmbeddedFileProvider(Assembly assembly, string root)
                : this(assembly, root, ResolveLastModified(assembly))
            {
            }
    
            /// <summary>
            /// Initializes a new instance of <see cref="ManifestEmbeddedFileProvider"/>.
            /// </summary>
            /// <param name="assembly">The assembly containing the embedded files.</param>
            /// <param name="root">The relative path from the root of the manifest to use as root for the provider.</param>
            /// <param name="lastModified">The LastModified date to use on the <see cref="IFileInfo"/> instances
            /// returned by this <see cref="IFileProvider"/>.</param>
            public ManifestEmbeddedFileProvider(Assembly assembly, string root, DateTimeOffset lastModified)
                : this(assembly, ManifestParser.Parse(assembly).Scope(root), lastModified)
            {
            }
    
            /// <summary>
            /// Initializes a new instance of <see cref="ManifestEmbeddedFileProvider"/>.
            /// </summary>
            /// <param name="assembly">The assembly containing the embedded files.</param>
            /// <param name="root">The relative path from the root of the manifest to use as root for the provider.</param>
            /// <param name="manifestName">The name of the embedded resource containing the manifest.</param>
            /// <param name="lastModified">The LastModified date to use on the <see cref="IFileInfo"/> instances
            /// returned by this <see cref="IFileProvider"/>.</param>
            public ManifestEmbeddedFileProvider(Assembly assembly, string root, string manifestName, DateTimeOffset lastModified)
                : this(assembly, ManifestParser.Parse(assembly, manifestName).Scope(root), lastModified)
            {
            }
    
            internal ManifestEmbeddedFileProvider(Assembly assembly, EmbeddedFilesManifest manifest, DateTimeOffset lastModified)
            {
                if (assembly == null)
                {
                    throw new ArgumentNullException(nameof(assembly));
                }
    
                if (manifest == null)
                {
                    throw new ArgumentNullException(nameof(manifest));
                }
    
                Assembly = assembly;
                Manifest = manifest;
                _lastModified = lastModified;
            }
    
            /// <summary>
            /// Gets the <see cref="Assembly"/> for this provider.
            /// </summary>
            public Assembly Assembly { get; }
    
            internal EmbeddedFilesManifest Manifest { get; }
    
            /// <inheritdoc />
            public IDirectoryContents GetDirectoryContents(string subpath)
            {
                var entry = Manifest.ResolveEntry(subpath);
                if (entry == null || entry == ManifestEntry.UnknownPath)
                {
                    return NotFoundDirectoryContents.Singleton;
                }
    
                if (!(entry is ManifestDirectory directory))
                {
                    return NotFoundDirectoryContents.Singleton;
                }
    
                return new ManifestDirectoryContents(Assembly, directory, _lastModified);
            }
    
            /// <inheritdoc />
            public IFileInfo GetFileInfo(string subpath)
            {
                var entry = Manifest.ResolveEntry(subpath);
                switch (entry)
                {
                    case null:
                        return new NotFoundFileInfo(subpath);
                    case ManifestFile f:
                        return new ManifestFileInfo(Assembly, f, _lastModified);
                    case ManifestDirectory d when d != ManifestEntry.UnknownPath:
                        return new NotFoundFileInfo(d.Name);
                }
    
                return new NotFoundFileInfo(subpath);
            }
    
            /// <inheritdoc />
            public IChangeToken Watch(string filter)
            {
                if (filter == null)
                {
                    throw new ArgumentNullException(nameof(filter));
                }
    
                return NullChangeToken.Singleton;
            }
    
            private static DateTimeOffset ResolveLastModified(Assembly assembly)
            {
                var result = DateTimeOffset.UtcNow;
    
                if (!string.IsNullOrEmpty(assembly.Location))
                {
                    try
                    {
                        result = File.GetLastWriteTimeUtc(assembly.Location);
                    }
                    catch (PathTooLongException)
                    {
                    }
                    catch (UnauthorizedAccessException)
                    {
                    }
                }
    
                return result;
            }
        }

    可以读取嵌入资源的文件

    在项目中添加user.txt,修改生成操作为嵌入资源

    class Program
        {
            static void Main(string[] args)
            {
                var fileProvider = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
                var fileInfo = fileProvider.GetFileInfo("user.txt");
                using (var streamReader = new StreamReader(fileInfo.CreateReadStream()))
                {
                    Console.WriteLine(streamReader.ReadToEnd());
                }
    
    
                Console.Read();
    
            }
        }

    三、CompositeFileProvider

      

    /// <summary>
        /// Looks up files using a collection of <see cref="IFileProvider"/>.
        /// </summary>
        public class CompositeFileProvider : IFileProvider
        {
            private readonly IFileProvider[] _fileProviders;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="CompositeFileProvider" /> class using a collection of file provider.
            /// </summary>
            /// <param name="fileProviders">The collection of <see cref="IFileProvider" /></param>
            public CompositeFileProvider(params IFileProvider[] fileProviders)
            {
                _fileProviders = fileProviders ?? new IFileProvider[0];
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="CompositeFileProvider" /> class using a collection of file provider.
            /// </summary>
            /// <param name="fileProviders">The collection of <see cref="IFileProvider" /></param>
            public CompositeFileProvider(IEnumerable<IFileProvider> fileProviders)
            {
                if (fileProviders == null)
                {
                    throw new ArgumentNullException(nameof(fileProviders));
                }
                _fileProviders = fileProviders.ToArray();
            }
    
            /// <summary>
            /// Locates a file at the given path.
            /// </summary>
            /// <param name="subpath">The path that identifies the file. </param>
            /// <returns>The file information. Caller must check Exists property. This will be the first existing <see cref="IFileInfo"/> returned by the provided <see cref="IFileProvider"/> or a not found <see cref="IFileInfo"/> if no existing files is found.</returns>
            public IFileInfo GetFileInfo(string subpath)
            {
                foreach (var fileProvider in _fileProviders)
                {
                    var fileInfo = fileProvider.GetFileInfo(subpath);
                    if (fileInfo != null && fileInfo.Exists)
                    {
                        return fileInfo;
                    }
                }
                return new NotFoundFileInfo(subpath);
            }
    
            /// <summary>
            /// Enumerate a directory at the given path, if any.
            /// </summary>
            /// <param name="subpath">The path that identifies the directory</param>
            /// <returns>Contents of the directory. Caller must check Exists property.
            /// The content is a merge of the contents of the provided <see cref="IFileProvider"/>.
            /// When there is multiple <see cref="IFileInfo"/> with the same Name property, only the first one is included on the results.</returns>
            public IDirectoryContents GetDirectoryContents(string subpath)
            {
                var directoryContents = new CompositeDirectoryContents(_fileProviders, subpath);
                return directoryContents;
            }
    
            /// <summary>
            /// Creates a <see cref="IChangeToken"/> for the specified <paramref name="pattern"/>.
            /// </summary>
            /// <param name="pattern">Filter string used to determine what files or folders to monitor. Example: **/*.cs, *.*, subFolder/**/*.cshtml.</param>
            /// <returns>An <see cref="IChangeToken"/> that is notified when a file matching <paramref name="pattern"/> is added, modified or deleted.
            /// The change token will be notified when one of the change token returned by the provided <see cref="IFileProvider"/> will be notified.</returns>
            public IChangeToken Watch(string pattern)
            {
                // Watch all file providers
                var changeTokens = new List<IChangeToken>();
                foreach (var fileProvider in _fileProviders)
                {
                    var changeToken = fileProvider.Watch(pattern);
                    if (changeToken != null)
                    {
                        changeTokens.Add(changeToken);
                    }
                }
    
                // There is no change token with active change callbacks
                if (changeTokens.Count == 0)
                {
                    return NullChangeToken.Singleton;
                }
                
                return new CompositeChangeToken(changeTokens);
            }
    
            /// <summary>
            /// Gets the list of configured <see cref="IFileProvider" /> instances.
            /// </summary>
            public IEnumerable<IFileProvider> FileProviders => _fileProviders;
        }
    CompositeFileProvider 可以看成是一种组合模式,接收多个IFileProvider
    获取IFileInfo的时候遍历
    IFileProvider获取

    class Program
        {
            static void Main(string[] args)
            {
                var services = new ServiceCollection();
                var provider1 = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "files"));
    
                var provider2 = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
    
                provider1.Watch("data.txt").RegisterChangeCallback(state => { Console.WriteLine("Change"); }, "");
                services.AddTransient<IFileProvider>(p => provider1);
                services.AddTransient<IFileProvider>(p => provider2);
                services.AddTransient<CompositeFileProvider>();
                var provider = services.BuildServiceProvider();
                var fileProvider = provider.GetService<CompositeFileProvider>();
    
                var fileInfo = fileProvider.GetFileInfo("data.txt");
                using (var streamReader = new StreamReader(fileInfo.CreateReadStream()))
                {
                    var result = streamReader.ReadToEnd();
                    Console.WriteLine(result);
                }
                var contents = fileProvider.GetDirectoryContents("sub");
                foreach (var item in contents)
                {
                    Console.WriteLine(item.Name);
                }
    
    
                Console.Read();
    
            }
        }

    IFileProvider有Watch方法,可以监听某个文件,当文件被修改时,会触发相应的操作

    总结:了解了netcore文件系统的原理,可以自定义一个自己的文件提供器。比如获取阿里云Oss的文件

  • 相关阅读:
    异象石(引理证明)
    Codeforces Round #664 (Div. 2)
    2020 年百度之星&#183;程序设计大赛
    Codeforces Round #663 (Div. 2)
    Codeforces Round #662 (Div. 2)
    相等运算符
    Unicode编码
    算术运算符
    强制类型转换到Boolean
    强制类型转换到Number
  • 原文地址:https://www.cnblogs.com/lanpingwang/p/12540043.html
Copyright © 2011-2022 走看看