数据流(并行转化数据)

本文介绍了一种使用C#实现的文件处理流程,通过数据流管道的方式读取指定路径下的所有文本文件,加载文件中的每一行,进一步将行拆分为单词,并最终展示这些单词。此外,还提供了一个案例,演示了从指定URI下载字符串,创建并过滤单词列表,查找颠倒的单词,并打印结果的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 static IEnumerable<string> GetFileNames(string path)
        {
            foreach (var fileName in Directory.EnumerateFiles(path, "*.txt"))
            {
                yield return fileName;
            }
        }
        static IEnumerable<string> LoadLines(IEnumerable<string> fileNames)
        {
            foreach (var fileName in fileNames)
            {
                using (FileStream stream = File.OpenRead(fileName))
                {
                    var reader = new StreamReader(stream,Encoding.Default);
                    string line = null;
                    while ((line = reader.ReadLine()) != null) yield return line;
                }
            }
        }
        static IEnumerable<string> GetWords(IEnumerable<string> lines)
        {
            foreach (var line in lines)
            {
                string[] words = line.Split(' ', ';', '.', ',');
                foreach (var word in words)
                {
                    if (!string.IsNullOrEmpty(word)) yield return word;
                }
            }
        }

        static ITargetBlock<string> SetupPipeline()
        {
            var fileNamesForPath = new TransformBlock<string, IEnumerable<string>>(path => GetFileNames(path));
            var lines = new TransformBlock<IEnumerable<string>, IEnumerable<string>>(fileNames => LoadLines(fileNames));
            var words = new TransformBlock<IEnumerable<string>, IEnumerable<string>>(lines2 => GetWords(lines2));
            var display = new ActionBlock<IEnumerable<string>>(coll =>
            {
                foreach (var s in coll) Console.WriteLine(s);
            });
            fileNamesForPath.LinkTo(lines);
            lines.LinkTo(words);
            words.LinkTo(display);
            return fileNamesForPath;
        }

//调用

var target = SetupPipeline();
            target.Post(@"C:\Users\chenss\Desktop");

//案例二

 var downloadString = new TransformBlock<string, string>(uri =>
           {
               string strResult = string.Empty;
               using (var reader = new StreamReader(uri, Encoding.Default))
               {
                   while (reader.ReadLineAsync().Result != null)
                   {
                       strResult += reader.ReadLineAsync().Result + " ";
                   }
               }
               Console.WriteLine($"下载 {strResult} ...");
               return strResult;
           });
            var createWordList = new TransformBlock<string, string[]>(text =>
            {
                Console.WriteLine("创建单词列表 ...");
                char[] tokens = text.Select(c => char.IsLetter(c) ? c : ' ').ToArray();
                text = new string(tokens);
                return text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            });
            var filterWordList = new TransformBlock<string[], string[]>(words =>
            {
                Console.WriteLine("筛选单词列表 ...");
                return words.Where(word => word.Length > 3).Distinct().ToArray();
            });
            var findReversedWords = new TransformManyBlock<string[], string>(words =>
            {
                Console.WriteLine("查找颠倒的单词 ...");
                var wordsSet = new HashSet<string>(words);
                var query = from word in words.AsParallel() select word;
                return query;
            });
            var printReversedWords = new ActionBlock<string>(reversedWord =>
            {
                Console.WriteLine("Found reversed words {0}/{1}", reversedWord, new string(reversedWord.Reverse().ToArray()));
            });
            //var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
            downloadString.LinkTo(createWordList);
            createWordList.LinkTo(filterWordList);
            filterWordList.LinkTo(findReversedWords);
            findReversedWords.LinkTo(printReversedWords);
            downloadString.Post(@"C:\Users\chenss\Desktop\Test.txt");
            downloadString.Complete();
            printReversedWords.Completion.Wait();

### 数据流图到层次结构图的转换 数据流图(DFD)描述了系统的逻辑流程以及各个组件之间的交互方式,而层次结构图则更侧重于展示系统内部各模块间的隶属关系和控制结构。为了实现从数据流图向层次结构图的有效转变,通常遵循以下原则: #### 原理说明 在转换过程中,顶层的数据流图中的主要过程会被视为高层次模块,在此基础上进一步细分低层子模块直至最底层的具体操作[^1]。 对于每一个处理节点,如果其复杂度较高,则应将其分解成若干个更为简单的子处理单元;这些子单元之间可能存在调用关系或是并行执行的关系。通过这种方式构建起来的就是一种树状或网状的层次化架构模型。 #### 使用工具支持 目前市面上存在多种软件可以帮助完成这一工作,例如Visio、Lucidchart等可视化建模工具均提供了绘制这两种图表的功能,并允许用户自定义连接线样式来表示不同类型的关联。此外还有一些专门用于需求分析与设计阶段的专业CASE (Computer-Aided Software Engineering) 工具如Enterprise Architect也能够很好地辅助这项任务。 #### 实际案例演示 假设有一个图书馆管理系统作为例子来进行具体的操作示范: ```plaintext // 顶层 DFD 展现借阅书籍的整体业务流程 Process(0): 用户请求 -> Process(1): 查询库存 -> Store: 图书数据库 -> Process(2): 更新记录 -> External Entity: 还书处 // 中间层细化查询库存的过程 Process(1.1): 接收ISBN号输入 -> Decision Point: 是否有该书?-> Yes Path(Process 1.2), No Path(Message Box) // 底层详细描绘更新记录部分 Process(2.1): 修改图书状态为已借出 -> Log File: 记录日志信息 -> Notify User Interface: 显示成功消息 ``` 上述内容可以通过如下步骤转化为层次结构图: - 将`Process(0)`设为主控模块; - `Process(1)`及其下级细分为两个独立分支分别对应“判断是否有此书”的决策路径; - 对于`Process(2)`同样做类似的拆分处理得到最终版本。 这样就完成了由上至下的逐层解析,形成了清晰直观的层次结构表达形式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

双叶红于二月花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值