Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Souborové aplikace jsou programy obsažené v jednom *.cs souboru, který sestavíte a spustíte bez odpovídajícího souboru projektu (*.csproj). Souborové aplikace jsou ideální pro výuku jazyka C#, protože mají menší složitost: Celý program je uložený v jednom souboru. Aplikace založené na souborech jsou také užitečné pro vytváření nástrojů příkazového řádku. Na platformách Unix můžete spouštět aplikace založené na souborech pomocí #!direktiv (shebang).
V tomto kurzu se naučíte:
- Vytvořte program založený na souborech.
- Přidání podpory unixových shebangů (
#!). - Čtení argumentů příkazového řádku
- Zpracování standardního vstupu
- Napište výstup obrázku ASCII.
- Zpracování argumentů příkazového řádku
- Použijte analyzované výsledky příkazového řádku.
- Otestujte konečnou aplikaci.
Vytvoříte souborový program, který zapíše text jako obrázek ASCII. Aplikace je obsažena v jednom souboru, používá balíčky NuGet a implementuje základní funkce.
Požadavky
- .NET 10 SDK. Stáhněte si ho z webu pro stahování .NET.
- Visual Studio Code. Stáhněte si ji z domovské stránky editoru Visual Studio Code.
- (Volitelné) Rozšíření C# DevKit pro Visual Studio Code Stáhněte si ho z marketplace editoru Visual Studio Code.
Vytvoření programu založeného na souborech
Otevřete Visual Studio Code a vytvořte nový soubor s názvem
AsciiArt.cs. Zadejte následující text:Console.WriteLine("Hello, world!");Uložte soubor. Pak otevřete integrovaný terminál v editoru Visual Studio Code a zadejte:
dotnet AsciiArt.cs
Při prvním spuštění tohoto programu dotnet hostitel sestaví spustitelný soubor ze zdrojového souboru, uloží artefakty sestavení do dočasné složky a potom spustí vytvořený spustitelný soubor. Toto prostředí můžete ověřit opětovným zadáním dotnet AsciiArt.cs . Tentokrát hostitel zjistí, dotnet že spustitelný soubor je aktuální a spustí spustitelný soubor bez jeho opětovného sestavení. Nezobrazuje se žádný výstup sestavení.
Předchozí kroky ukazují, že souborové aplikace nejsou soubory skriptů. Jedná se o zdrojové soubory jazyka C#, které dotnet hostitel sestaví pomocí vygenerovaného souboru projektu v dočasné složce. Jeden z řádků výstupu zobrazených při sestavování programu by měl vypadat přibližně takto (ve Windows):
AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll
Na platformách Unix je výstupní složka podobná této:
AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll
Tento výstup vám řekne, kam se umístí dočasné soubory a výstupy sestavení. V tomto kurzu se při každé úpravě zdrojového souboru dotnet hostitel před spuštěním aktualizuje spustitelný soubor.
Souborové aplikace jsou běžné programy jazyka C#. Jediným omezením je, že je musíte zapsat do jednoho zdrojového souboru. Jako vstupní bod můžete použít příkazy nejvyšší úrovně nebo klasickou Main metodu. Můžete deklarovat libovolné typy: třídy, rozhraní a struktury. Algoritmy můžete strukturovat v programu založeném na souborech stejně jako v jakémkoli programu jazyka C#. Můžete dokonce deklarovat více oborů názvů pro uspořádání kódu. Pokud zjistíte, že se pro jeden soubor příliš rozrůstá program založený na souborech, můžete ho převést na projektový program a rozdělit zdroj na více souborů. Souborové aplikace jsou skvělým nástrojem pro vytváření prototypů. Můžete začít experimentovat s minimální režií a prokázat koncepty a vytvářet algoritmy.
Podpora pro Unix shebang (#!)
Poznámka:
#! Podpora direktiv se vztahuje pouze na platformy Unix. Pro Windows neexistuje žádná podobná direktiva pro přímé spuštění programu v jazyce C#. Ve Windows musíte použít dotnet na příkazovém řádku.
V unixu spusťte aplikace založené na souborech přímo zadáním pouze názvu zdrojového souboru. Místo použití dotnet AsciiArt.cszadejte název zdrojového souboru na příkazovém řádku. Potřebujete provést dvě změny:
Nastavte oprávnění ke spuštění zdrojového souboru:
chmod +x AsciiArt.csPřidejte direktivu shebang (
#!) jako první řádekAsciiArt.cssouboru:#!/usr/local/share/dotnet/dotnet
Umístění dotnet se může lišit v různých instalacích systému Unix. Pomocí příkazu which dotnet vyhledejte dotnet hostitele ve vašem prostředí.
Alternativně můžete použít #!/usr/bin/env dotnet k automatickému určení cesty dotnet z proměnné prostředí PATH.
#!/usr/bin/env dotnet
Po provedení těchto dvou změn můžete program spustit přímo z příkazového řádku:
./AsciiArt.cs
Pokud chcete, můžete rozšíření odebrat, abyste místo toho mohli psát ./AsciiArt . Do zdrojového #! souboru můžete přidat i v případě, že používáte Windows. Příkazový řádek Windows nepodporuje #!, ale kompilátor jazyka C# umožňuje direktivu v souborových aplikacích na všech platformách.
Čtení argumentů příkazového řádku
Teď na příkazovém řádku napište všechny argumenty do výstupu.
Nahraďte aktuální obsah
AsciiArt.csnásledujícím kódem:if (args.Length > 0) { string message = string.Join(' ', args); Console.WriteLine(message); }Tuto verzi můžete spustit zadáním následujícího příkazu:
dotnet AsciiArt.cs -- This is the command line.Tato
--možnost označuje, že všechny následující argumenty příkazů by měly být předány do programu AsciiArt. ArgumentyThis is the command line.jsou předány jako pole řetězců, kde každý řetězec je jedno slovo:This,is,the,command, aline..
Tato verze ukazuje tyto nové koncepty:
- Předdefinovaná proměnná
argspředá argumenty příkazového řádku programu. Proměnnáargsje pole řetězců:string[]. Pokud je délkaargs0, nebyly zadány žádné argumenty. V opačném případě je každé slovo v seznamu argumentů uloženo v odpovídající položce v poli. - Metoda
string.Joinspojí více řetězců do jednoho řetězce se zadaným oddělovačem. V tomto případě je oddělovač jedinou mezerou. - Console.WriteLine zapíše řetězec do standardní výstupní konzoly následované novým řádkem.
Zpracování standardního vstupu
Předchozí kód zpracovává správně argumenty příkazového řádku. Teď přidejte kód pro zpracování čtení vstupu ze standardního vstupu (stdin) místo argumentů příkazového řádku.
Do příkazu, který jste přidali v předchozím kódu, přidejte následující
elseklauzuliif:else { while (Console.ReadLine() is string line && line.Length > 0) { Console.WriteLine(line); } }Předchozí kód přečte vstup konzoly, dokud se nečte prázdný řádek nebo
nullpřečte. (Metoda Console.ReadLine vrátínull, pokud je vstupní datový proud zavřený zadáním ctrl+C.)Otestujte čtení standardního vstupu vytvořením nového textového souboru ve stejné složce. Pojmenujte soubor
input.txta přidejte následující řádky:Hello from ... dotnet! You can create file-based apps in .NET 10 and C# 14 Have fun writing useful utilitiesŘádky nechte krátké, aby se správně naformátovali, když přidáte funkci pro použití obrázků ASCII.
Spusťte program znovu.
S použitím basha:
cat input.txt | dotnet AsciiArt.csNebo pomocí PowerShellu:
Get-Content input.txt | dotnet AsciiArt.cs
Teď může program přijímat argumenty příkazového řádku nebo standardní vstup.
Zápis výstupu obrázku ASCII
Dále přidejte balíček, který podporuje ASCII art, Colorful.Console. Pokud chcete přidat balíček do programu založeného na souborech, použijte direktivu #:package .
Přidejte následující direktivu za direktivu
#!do vašeho souboruAsciiArt.cs:#:package Colorful.Console@1.2.15Důležité
1.2.15Verze byla nejnovější verzíColorful.Consolebalíčku při poslední aktualizaci tohoto kurzu. Na stránce NuGet balíčku vyhledejte nejnovější verzi a ujistěte se, že používáte verzi balíčku s nejnovějšími opravami zabezpečení.Změňte místo toho řádky, které volají
Console.WriteLinemetoduColorful.Console.WriteAscii:Colorful.Console.WriteAscii(line);Spusťte program. Místo ozvěny textu se zobrazí výstup ASCII art.
Možnosti příkazů procesu
Dále přidejte analýzu příkazového řádku. Aktuální verze zapisuje každé slovo jako jiný řádek výstupu. Argumenty příkazového řádku, které přidáte, podporují dvě funkce:
Citace více slov, která by se měla napsat na jeden řádek:
AsciiArt.cs "This is line one" "This is another line" "This is the last line"--delayPřidejte mezi každý řádek možnost pozastavení:AsciiArt.cs --delay 1000
Uživatelé můžou používat oba argumenty společně.
Většina aplikací příkazového řádku potřebuje analyzovat argumenty příkazového řádku, aby bylo možné efektivně zpracovávat možnosti, příkazy a vstupy uživatelů.
KnihovnaSystem.CommandLine poskytuje komplexní možnosti pro zpracování příkazů, dílčích příkazů, možností a argumentů. Můžete se soustředit na to, co vaše aplikace dělá, a ne na mechaniku analýzy vstupu příkazového řádku.
Knihovna System.CommandLine nabízí několik klíčových výhod:
- Automatické generování a ověřování textu nápovědy
- Podpora konvencí příkazového řádku POSIX a Windows
- Integrované možnosti dokončování tabulátoru
- Konzistentní chování analýzy napříč aplikacemi
System.CommandLinePřidejte balíček. Přidejte tuto direktivu za existující direktivu balíčku:#:package System.CommandLine@2.0.0Důležité
2.0.0Verze byla nejnovější verzí, kdy byl tento kurz naposledy aktualizován. Pokud je k dispozici novější verze, použijte nejnovější verzi, abyste měli jistotu, že máte nejnovější balíčky zabezpečení. Na stránce NuGet balíčku vyhledejte nejnovější verzi a ujistěte se, že používáte verzi balíčku s nejnovějšími opravami zabezpečení.Přidejte potřebné příkazy using v horní části souboru (za direktivy
#!a#:packagedirektivy):using System.CommandLine; using System.CommandLine.Parsing;Definujte možnost zpoždění a argument zpráv. Přidejte následující kód, který vytvoří
CommandLine.OptionobjektyCommandLine.Argument, které představují možnost a argument příkazového řádku:Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds.", DefaultValueFactory = parseResult => 100 }; Argument<string[]> messagesArgument = new("Messages") { Description = "Text to render." };V aplikacích příkazového řádku obvykle začínají možnostmi
--(dvojitá pomlčka) a můžou přijímat argumenty. Možnost--delaypřijímá celočíselnou hodnotu, která určuje zpoždění v milisekundách. DefinujemessagesArgument, jak se všechny zbývající tokeny po parsování možností parsují jako text. Každý token se stane samostatným řetězcem v poli, ale text může obsahovat více slov v jednom tokenu. Například"This is one message"se stane jedním tokenem, zatímcoThis is four tokensse stanou čtyřmi samostatnými tokeny.Předchozí kód definuje typ argumentu
--delaypro možnost a že argumenty jsou pole hodnotstring. Tato aplikace má pouze jeden příkaz, takže použijete kořenový příkaz.Vytvořte kořenový příkaz a nakonfigurujte ho s možností a argumentem. Přidejte argument a možnost do kořenového příkazu:
RootCommand rootCommand = new("Ascii Art file-based program sample"); rootCommand.Options.Add(delayOption); rootCommand.Arguments.Add(messagesArgument);Přidejte kód pro analýzu argumentů příkazového řádku a zpracování chyb. Tento kód ověří argumenty příkazového řádku a uloží parsované argumenty v objektu System.CommandLine.ParseResult :
ParseResult result = rootCommand.Parse(args); foreach (ParseError parseError in result.Errors) { Console.Error.WriteLine(parseError.Message); } if (result.Errors.Count > 0) { return 1; }
Předchozí kód ověří všechny argumenty příkazového řádku. Pokud se ověření nezdaří, aplikace zapíše do konzoly chyby a ukončí se.
Použití analyzovaných výsledků příkazového řádku
Teď dokončete aplikaci, aby používala parsované možnosti a napsala výstup. Nejprve definujte záznam, který bude obsahovat parsované možnosti. Aplikace založené na souborech můžou obsahovat deklarace typů, jako jsou záznamy a třídy. Musí být po všech příkazech nejvyšší úrovně a místních funkcích.
recordPřidejte deklaraci pro uložení zpráv a hodnoty možnosti zpoždění:public record AsciiMessageOptions(string[] Messages, int Delay);Před deklaraci záznamu přidejte následující místní funkci. Tato metoda zpracovává argumenty příkazového řádku i standardní vstup a vrací novou instanci záznamu:
async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result) { int delay = result.GetValue(delayOption); List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()]; if (messages.Count == 0) { while (Console.ReadLine() is string line && line.Length > 0) { Colorful.Console.WriteAscii(line); await Task.Delay(delay); } } return new([.. messages], delay); }Vytvořte místní funkci pro zápis artu ASCII se zadaným zpožděním. Tato funkce zapíše každou zprávu v záznamu se zadaným zpožděním mezi jednotlivými zprávami:
async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Klauzuli
if, kterou jste napsali dříve, nahraďte následujícím kódem, který zpracovává argumenty příkazového řádku a zapisuje výstup:var parsedArgs = await ProcessParseResults(result); await WriteAsciiArt(parsedArgs); return 0;
Vytvořili record jste typ, který poskytuje strukturu pro parsované možnosti a argumenty příkazového řádku. Nové místní funkce vytvoří instanci záznamu a použije záznam k zápisu výstupu ASCII art.
Otestování konečné aplikace
Otestujte aplikaci spuštěním několika různých příkazů. Pokud máte potíže, tady je hotová ukázka pro porovnání s tím, co jste vytvořili:
#!/usr/bin/env dotnet
#:package Colorful.Console@1.2.15
#:package System.CommandLine@2.0.0
using System.CommandLine;
using System.CommandLine.Parsing;
Option<int> delayOption = new("--delay")
{
Description = "Delay between lines, specified as milliseconds.",
DefaultValueFactory = parseResult => 100
};
Argument<string[]> messagesArgument = new("Messages")
{
Description = "Text to render."
};
RootCommand rootCommand = new("Ascii Art file-based program sample");
rootCommand.Options.Add(delayOption);
rootCommand.Arguments.Add(messagesArgument);
ParseResult result = rootCommand.Parse(args);
foreach (ParseError parseError in result.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
if (result.Errors.Count > 0)
{
return 1;
}
var parsedArgs = await ProcessParseResults(result);
await WriteAsciiArt(parsedArgs);
return 0;
async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
{
int delay = result.GetValue(delayOption);
List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()];
if (messages.Count == 0)
{
while (Console.ReadLine() is string line && line.Length > 0)
{
// <WriteAscii>
Colorful.Console.WriteAscii(line);
// </WriteAscii>
await Task.Delay(delay);
}
}
return new([.. messages], delay);
}
async Task WriteAsciiArt(AsciiMessageOptions options)
{
foreach (string message in options.Messages)
{
Colorful.Console.WriteAscii(message);
await Task.Delay(options.Delay);
}
}
public record AsciiMessageOptions(string[] Messages, int Delay);
V tomto kurzu jste se naučili vytvořit souborový program, ve kterém program sestavíte v jednom souboru C#. Tyto programy nepoužívají soubor projektu a mohou používat direktivu #! v systémech Unix. Studenti můžou tyto programy vytvářet po vyzkoušení našich online kurzů a před vytvořením větších aplikací založených na projektu. Souborové aplikace jsou také skvělou platformou pro nástroje příkazového řádku.