C# 基礎知識系列- 17 實戰篇 編寫一個小工具(1)

来源:https://www.cnblogs.com/c7jie/archive/2020/05/07/12842459.html
-Advertisement-
Play Games

0. 前言 這是對C 基礎系列的一個總結,現在我們利用之前學到的知識做一個小小的工具來給我們使用。 如果有看過IO篇的小伙伴,應該有印象。當時我提過一個場景描述,我們在平時使用系統的時候,經常會為了找某個文件的位置而煩惱。那麼我們現在嘗試寫一個控制台程式來幫助我們找文件的具體位置。 1. 分析 好, ...


0. 前言

這是對C# 基礎系列的一個總結,現在我們利用之前學到的知識做一個小小的工具來給我們使用。

如果有看過IO篇的小伙伴,應該有印象。當時我提過一個場景描述,我們在平時使用系統的時候,經常會為了找某個文件的位置而煩惱。那麼我們現在嘗試寫一個控制台程式來幫助我們找文件的具體位置。

1. 分析

好,大家應該初步瞭解了需求內容。然後讓我們來做一個簡單的需求分析:

  1. 簡單分析一下需求包括哪些功能點
  2. 規劃各個功能點的實現方式

嗯,理論上講還有一大堆的步驟,但因為是個練手的小項目就不扯那麼多沒用的了。簡單來講就是,分兩步:

  1. 抓取系統可以訪問的所有文件,並保存其全路徑
  2. 根據輸入的參數查詢文件的全路徑

需求分析完了,然後尋找可以實現的技術,我們現有的技術有IO、文件/路徑操作、任務模式等技術,那麼可以供我們選擇的技術一目瞭然了:通過文件/目錄/路徑API訪問所有的文件目錄,使用字典保存,然後使用Linq查詢文件所在目錄。

OK,需求分析完了,技術也確認了。那麼我們現在開始吧,小伙伴們跟緊了哦,車速不快的。

2. 開始

這裡簡單演示一下如何用Rider和VSCode、Visual Studio2019創建項目。

2.1. 創建一個名為 FileFinder的項目

a.使用Rider:

點擊箭頭所指方向:

image-20200506213821025

先在左側選擇Console Application,然後修改 Project name,最後修改 Solution Directory為自己的目錄:

image-20200506214124769

然後點擊 Create,創建完成結果如下:

image-20200506214423649

Rider創建項目的步驟在Windows、Linux、Mac三個系統都是一樣的。

b. 使用VS Code創建項目

使用VS Code創建項目與Rider和Visual Studio有所不同,步驟比較繁瑣:

先在合適的文件夾下創建一個fileFinder目錄,併在fileFinder目錄下打開命令行,輸入以下命令:

dotnet new sln -n fileFinder # 創建一個名為 fileFinder 的解決方案
dotnet new console -n fileFinder # 創建一個名為 fileFinder的控制台程式
dotnet sln add fileFinder # 把 fileFinder的項目添加到fileFinder的解決方案里

最終結果應該是這樣的:

image-20200506220949536

c.使用 Visual Studio

file

選擇【創建新項目】
file
註意框住地方的選擇,選控制台程式,然後點擊下一步
file
填寫項目名稱、路徑,點擊創建
file

2.2 開始編寫程式

現在我們創建完成了一個項目,然後可以開始編寫我們的程式了。

首先創建一個遍歷所有目錄的方法:

public static Dictionary<string,List<string>> OverDirectories()
{
    //
    return null;
}

現在我們有一個問題,因為Windows的特殊性,目錄結構分為了磁碟:\文件夾這種形式,我們沒法通過設置一個根目錄去遍歷,這時候就要藉助一下官方文檔了。通過查閱API,我們發現一個類:

public sealed class DriveInfo : System.Runtime.Serialization.ISerializable//提供對有關驅動器的信息的訪問。

有一個方法:

public static System.IO.DriveInfo[] GetDrives ();// 檢索電腦上的所有邏輯驅動器的驅動器名稱。

再看一下屬性:

public string Name { get; }// 獲取驅動器的名稱,如 C:\。
public System.IO.DirectoryInfo RootDirectory { get; }// 獲取驅動器的根目錄。

初步查看滿足我們的需要,先在Program.cs的頭添加命名空間引用:

using System.IO;

表示在這個代碼文件中會使用這個命名空間的類或者結構體等元素。

在項目中編寫一個方法:

public static void GetDrivers()
{
    var drives = DriveInfo.GetDrives();
    foreach(var drive in drives)
    {
        Console.WriteLine($"驅動器名稱:{drive.Name}:\t {drive.RootDirectory}");
    }
}

然後修改Main方法為:

static void Main(string[] args)
{
    GetDrivers();
}

運行程式,下圖是Linux系統的列印結果:(Rider/Visual Studio的運行程式快捷鍵是F5)

image-20200506224209939

經過完美符合我們的需求,修改GetDrivers方法,使其可以返回所有驅動器的根目錄:

先引入以下命名空間的引用:

using System.Linq;// Linq的支持
using System.Collections.Generic;//泛型集合的支持

修改方法如下:

public static List<DirectoryInfo> GetDrivers()
{
    var drives = DriveInfo.GetDrives();
    return drives.Select(p=>p.RootDirectory).ToList();
}

然後回到方法OverDirectories里,先獲取所有的驅動器,遍歷所有驅動器下的所有目錄和文件,之後對遍歷結果歸類:

修改OverrDirectories方法:

public static Dictionary<string,List<string>> OverDirectories(DirectoryInfo rootDirectory)
{
    var dict = new Dictionary<string, List<string>>();// 創建一個保存數據的 字典類型
    foreach(var file in rootDirectory.EnumerateFiles()) //枚舉當前目錄下的所有文件
    {
        var key = Path.GetFileNameWithoutExtension(file.Name); //獲取無擴展名的文件名
        if(!dict.ContainsKey(key)) //檢查dict是否存放過 文件名,如果沒有,則創建一個列表,如果有則在列表中添加一條文件的全路徑
        {
            dict[key] = new List<string>();
        }
        dict[key].Add(file.FullName);
    }

    // 枚舉當前目錄的子目錄,遞歸調用該方法
    var dirs = rootDirectory.EnumerateDirectories().Select(OverDirectories); 
    foreach(var dir in dirs)//處理返回的字典枚舉,將數據合併到當前dict變數中
    {
        foreach(var key in dir.Keys)
        {
            if(!dict.ContainsKey(key))
            {
                dict[key] = new List<string>();
            }
            dict[key].AddRange(dir[key]);
        }
    }
    // 返回結果
    return dict;
}

我們簡單測試一下,修改Main方法:

static void Main(string[] args)
{
    var drivers = GetDrivers();
    var results = OverDirectories(drivers[0]);
    Console.WriteLine(results);
}

嗯,如果不出意外的話,你應該能得到類似如下的提示:

image-20200506234510641

這是因為在系統中(不管哪種系統)會有一些文件或者目錄是我們沒有許可權訪問的,這時候就必須用try/catch處理這些沒有訪問許可權的目錄和文件。因為我們平時使用不會 把文件放到這些目錄下麵,所以我們可以簡單的略過這些目錄。

同時觀察一下,GetDrivers 返回的是一組DirectoryInfo實例,而OverDirectories每次處理一個目錄,然後返回一個字典集合,所以我們需要整合這些集合,但我們在OverDirectories里編寫過相似的代碼,為了減少重覆代碼的編寫,提取這部分代碼為一個方法:

public static Dictionary<string,List<string>> Concat(params Dictionary<string,List<string>>[] dicts)
{
    var dict = new Dictionary<string,List<string>>();
    foreach(var dir in dicts)
    {
        foreach(var key in dir.Keys)
        {
            if(!dict.ContainsKey(key))
            {
                dict[key] = new List<string>();
            }
            dict[key].AddRange(dir[key]);
        }
    }
    return dict;
}

params 是C#可變參數列表關鍵字,聲明方式: params T[] values。表示方法可以接收任意個T類型的參數,方法中接到的是一個數組

繼續改造 OverDirectories方法,增加異常處理:

public static Dictionary<string,List<string>> OverDirectories(DirectoryInfo rootDirectory)
{
    var dict = new Dictionary<string, List<string>>();
    IEnumerable<FileInfo> files = new List<FileInfo>();
    try
    {
        files = rootDirectory.EnumerateFiles();
    }
    catch(Exception e)
    {
        Console.WriteLine($"錯誤信息:{e}");//列印錯誤信息
    }

    foreach(var file in files)
    {
        var key = Path.GetFileNameWithoutExtension(file.Name);
        if(!dict.ContainsKey(key))
        {
            dict[key] = new List<string>();
        }
        dict[key].Add(file.FullName);
    }

    try
    {
        var dicts = rootDirectory.EnumerateDirectories().Select(OverDirectories);    
        return Concat(dicts.Append(dict).ToArray());
    }
    catch (System.Exception e)
    {
        Console.WriteLine($"錯誤信息:{e}");//列印錯誤信息
    }
    return dict;
}

最後修改 Main方法,使其支持使用用戶輸入的字元串進行查詢:

static void Main(string[] args)
{
    var drivers = GetDrivers();
    var results = Concat(drivers.Select(OverDirectories).ToArray());
    Console.WriteLine("請輸入要查詢的文件名:");
    var search = Console.ReadLine().Trim();
    var keys = results.Keys.Where(p=>p.Contains(search));

    foreach(var key in keys)
    {
        var list = results[key];
        Console.WriteLine("查找到路徑是:");
        foreach(var path in list)
        {
            Console.WriteLine(path);
        }
    }
}

3. 總結

代碼進行到這裡了,可以說基本功能已經完成。如果有小伙伴嘗試使用示例代碼的話,可能會遇到各種問題,下一篇繼續為大家在現有知識基礎上做優化,讓它成為一個真正意義上可以使用的小工具。

更多內容煩請關註我的博客《高先生小屋》

file


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • python在通過cmd安裝pandas時遇到ModuleNotFoundError: No module named 'pip'的報錯。 網上查詢後通過如下兩行cmd命令解決了 然後就可通過cmd安裝pandas啦 ...
  • 作者:iuxiaopeng https://www.cnblogs.com/paddix/p/5367116.html Synchronized 的基本使用 Synchronized 的作用主要有三個: 確保線程互斥的訪問同步代碼 保證共用變數的修改能夠及時可見 有效解決重排序問題 從語法上講,Sy ...
  • ```python import sys sys.path.append("./") import os import datetime import logging import platform from logging.handlers import RotatingFileHandler #... ...
  • 1.常用的DOC命令 DOC命令已經慢慢消失了,但是掌握還是好的 1.cd 目錄路徑:進入一個目錄 2.cd .. :進入父目錄 3.dir:查看本目錄的文件和子目錄列表 4.cls:清空屏幕目錄 5.上下鍵:查看敲過的命令 6.Tab建:自動補齊命令 2.常用的開發環境 入門:記事本,更強大的記事 ...
  • 使用阿裡雲ECS或者其他常見的VPS服務部署應用的時候,需要手動配置環境,並且監測ECS的行為,做補丁之類的,搞得有點複雜。好在很多雲廠商(阿裡雲、Azure等)提供了Serverless服務,藉助於Serverless,開發人員可以更加專註於代碼的開發,減少運維的成本。 Azure的部署直接集成在 ...
  • 學習視頻:https://www.bilibili.com/video/BV1FJ411v7hv?p=15 socket通信傳輸的位元組是什麼內容,客戶端和服務端要知道這個位元組是文件,是字元串還是其他?應該設計一個協定。例如在內容位元組前面插入一個位元組表示內容形式,0代表字元串,1代表文件...... ...
  • HTTP 響應狀態碼 | HTTP 狀態碼 | 涵義 | 解釋說明 | | : | : | : | | 200 | OK | 用於一般性的成功返回,不可用於請求錯誤返回 | | 201 | Created | 資源被創建 | | 202 | Accepted | 用於資源非同步處理的返回,僅表示請求已 ...
  • 就目前國內市場情況來看,快速開發平臺主要有兩種模式,有引擎模式和生成源代碼模式兩種,以國內力軟快速開發平臺為例,針對不懂編程的管理者/業務人員和開發人員,力軟糅合了兩種開發模式。 力軟以場景為中心的軟體代碼平臺,可實現管理者或業務人員線上輕鬆搭建,業務應用隨心而變,重點解決中小型企業全數字化管理、中 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...