Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Les applications basées sur des fichiers sont des programmes contenus dans un seul *.cs fichier généré et exécuté sans fichier de projet (*.csproj) correspondant. Les applications basées sur des fichiers sont idéales pour l’apprentissage de C# car elles ont moins de complexité : l’ensemble du programme est stocké dans un seul fichier. Les applications basées sur des fichiers sont également utiles pour créer des utilitaires de ligne de commande. Sur les plateformes Unix, les applications basées sur des fichiers peuvent être exécutées à l’aide #! de directives (shebang).
Dans ce tutoriel, vous allez :
- Créez un programme basé sur des fichiers.
- Ajoutez la prise en charge de shebang
#!() Unix. - Lire les arguments de ligne de commande.
- Gérer l’entrée standard.
- Écrire une sortie d’art ASCII.
- Traiter les arguments de ligne de commande.
- Utilisez les résultats de ligne de commande analysés.
- Testez l’application finale.
Vous créez un programme basé sur des fichiers qui écrit du texte en tant qu’art ASCII. L’application est contenue dans un seul fichier, utilise des packages NuGet qui implémentent certaines des fonctionnalités principales.
Prerequisites
- Kit de développement logiciel (SDK) .NET 10. Téléchargez-le à partir du site de téléchargement .NET.
- Visual Studio Code. Téléchargez-le à partir de la page d’accueil de Visual Studio Code.
- (Facultatif) Extension DevKit C# pour Visual Studio Code. Téléchargez-le à partir de la Place de marché Visual Studio Code.
Créer un programme basé sur des fichiers
Ouvrez Visual Studio Code et créez un fichier nommé
AsciiArt.cs. Tapez le texte suivant :Console.WriteLine("Hello, world!");Enregistrez le fichier. Ensuite, ouvrez le terminal intégré dans Visual Studio Code et tapez :
dotnet run AsciiArt.cs
La première fois que vous exécutez ce programme, l’hôte dotnet génère l’exécutable à partir de votre fichier source, stocke les artefacts de build dans un dossier temporaire, puis exécute l’exécutable créé. Vous pouvez vérifier cette expérience en tapant dotnet run AsciiArt.cs à nouveau. Cette fois, l’hôte dotnet détermine que l’exécutable est actif et exécute l’exécutable sans le générer à nouveau. Vous ne voyez aucune sortie de build.
Les étapes précédentes montrent que les applications basées sur des fichiers ne sont pas des fichiers de script. Il s’agit de fichiers sources C# générés à l’aide d’un fichier projet généré dans un dossier temporaire. Une des lignes de sortie affichées lorsque vous avez créé le programme doit ressembler à ceci (sur Windows) :
AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll
Sur les plateformes unix, le dossier de sortie est similaire à ce qui suit :
AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll
Cette sortie vous indique où sont placés les fichiers temporaires et les sorties de build. Tout au long de ce tutoriel, chaque fois que vous modifiez le fichier source, l’hôte dotnet met à jour l’exécutable avant son exécution.
Les applications basées sur des fichiers sont des programmes C# standard. La seule limitation est qu’elles doivent être écrites dans un fichier source. Vous pouvez utiliser des instructions de niveau supérieur ou une méthode classique Main comme point d’entrée. Vous pouvez déclarer tous les types : classes, interfaces et structs. Vous pouvez structurer les algorithmes dans un programme basé sur des fichiers identiques à ceux que vous feriez dans n’importe quel programme C#. Vous pouvez même déclarer plusieurs espaces de noms pour organiser votre code. Si vous trouvez qu’un programme basé sur un fichier augmente trop grand pour un seul fichier, vous pouvez le convertir en programme basé sur un projet et fractionner la source en plusieurs fichiers. Les applications basées sur des fichiers sont un excellent outil de prototypage. Vous pouvez commencer à expérimenter avec une surcharge minimale pour prouver les concepts et générer des algorithmes.
Prise en charge du shebang Unix (#!)
Note
La prise en charge des #! directives s’applique uniquement sur les plateformes Unix. Il n’existe pas de directive similaire pour Que Windows exécute directement un programme C#. Sur Windows, vous devez utiliser dotnet run sur la ligne de commande.
Sur unix, vous pouvez exécuter des applications basées sur des fichiers directement, en tapant le nom du fichier source sur la ligne de commande au lieu de dotnet run. Vous devez apporter deux modifications :
Définissez les autorisations d’exécution sur le fichier source :
chmod +x AsciiArt.csAjoutez une directive shebang (
#!) comme première ligne duAsciiArt.csfichier :#!/usr/local/share/dotnet/dotnet run
L’emplacement de dotnet peut être différent sur différentes installations unix. Utilisez la commande which dotnet pour localiser l’hôte dotnet dans votre environnement.
Vous pouvez également utiliser #!/usr/bin/env dotnet pour résoudre automatiquement le chemin dotnet à partir de la variable d’environnement PATH :
#!/usr/bin/env dotnet
Après avoir apporté ces deux modifications, vous pouvez exécuter le programme directement à partir de la ligne de commande :
./AsciiArt.cs
Si vous préférez, vous pouvez supprimer l’extension afin de pouvoir taper ./AsciiArt à la place. Vous pouvez ajouter le #! fichier source même si vous utilisez Windows. La ligne de commande Windows ne prend pas en charge #!, mais le compilateur C# autorise cette directive dans les applications basées sur des fichiers sur toutes les plateformes.
Lire les arguments de ligne de commande
À présent, écrivez tous les arguments sur la ligne de commande dans la sortie.
Remplacez le contenu actuel par
AsciiArt.csle code suivant :if (args.Length > 0) { string message = string.Join(' ', args); Console.WriteLine(message); }Vous pouvez exécuter cette version en tapant la commande suivante :
dotnet run AsciiArt.cs -- This is the command line.L’option
--indique que tous les arguments de commande suivants doivent être passés au programme AsciiArt. Les argumentsThis is the command line.sont passés sous la forme d’un tableau de chaînes, où chaque chaîne est un mot :This, ,is,the,commandetline..
Cette version illustre ces nouveaux concepts :
- Les arguments de ligne de commande sont passés au programme à l’aide de la variable
argsprédéfinie. Laargsvariable est un tableau de chaînes :string[]. Si la longueurargsest égale à 0, cela signifie qu’aucun argument n’a été fourni. Sinon, chaque mot de la liste d’arguments est stocké dans l’entrée correspondante dans le tableau. - La
string.Joinméthode joint plusieurs chaînes en une seule chaîne, avec le séparateur spécifié. Dans ce cas, le séparateur est un espace unique. - Console.WriteLine écrit la chaîne dans la console de sortie standard, suivie d’une nouvelle ligne.
Gérer l’entrée standard
Cela gère correctement les arguments de ligne de commande. À présent, ajoutez le code pour gérer la lecture de l’entrée à partir d’une entrée standard (stdin) au lieu d’arguments de ligne de commande.
Ajoutez la clause suivante
elseà l’instructionifque vous avez ajoutée dans le code précédent :else { while (Console.ReadLine() is string line && line.Length > 0) { Console.WriteLine(line); } }Le code précédent lit l’entrée de la console jusqu’à ce qu’une ligne vide soit une
nulllecture. (La Console.ReadLine méthode retournenullsi le flux d’entrée est fermé en tapant ctrl+C.)Testez la lecture de l’entrée standard en créant un fichier texte dans le même dossier. Nommez le fichier
input.txtet ajoutez les lignes suivantes :Hello from ... dotnet! You can create file-based apps in .NET 10 and C# 14 Have fun writing useful utilitiesGardez les lignes courtes afin qu’elles soient correctement mises en forme lorsque vous ajoutez la fonctionnalité pour utiliser l’art ASCII.
Réexécutez le programme.
Avec bash :
cat input.txt | dotnet run AsciiArt.csOu, avec PowerShell :
Get-Content input.txt | dotnet run AsciiArt.cs
À présent, votre programme peut accepter des arguments de ligne de commande ou une entrée standard.
Écrire une sortie ASCII Art
Ensuite, ajoutez un package qui prend en charge l’art ASCII, Color.Console. Pour ajouter un package à un programme basé sur des fichiers, vous utilisez la #:package directive.
Ajoutez la directive suivante après la
#!directive dans votre fichier AsciiArt.cs :#:package Colorful.Console@1.2.15Important
La version
1.2.15était la dernière version du package lors de laColorful.Consoledernière mise à jour de ce didacticiel. Consultez la page NuGet du package pour connaître la dernière version pour vous assurer d’utiliser une version de package avec les derniers correctifs de sécurité.Modifiez les lignes qui appellent
Console.WriteLineà utiliser la méthode à laColorful.Console.WriteAsciiplace :async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Exécutez le programme et vous voyez la sortie de l’art ASCII au lieu du texte en écho.
Options de commande de processus
Ensuite, ajoutons l’analyse de ligne de commande. La version actuelle écrit chaque mot sous la forme d’une ligne de sortie différente. Les arguments de ligne de commande que vous avez ajoutés prennent en charge deux fonctionnalités :
Citez plusieurs mots qui doivent être écrits sur une ligne :
AsciiArt.cs "This is line one" "This is another line" "This is the last line"Ajoutez une
--delayoption pour suspendre entre chaque ligne :AsciiArt.cs --delay 1000
Les utilisateurs doivent pouvoir utiliser les deux arguments ensemble.
La plupart des applications de ligne de commande doivent analyser efficacement les arguments de ligne de commande pour gérer efficacement les options, les commandes et l’entrée utilisateur. La System.CommandLine bibliothèque fournit des fonctionnalités complètes pour gérer les commandes, les sous-commandes, les options et les arguments, ce qui vous permet de vous concentrer sur ce que fait votre application plutôt que sur la mécanique de l’analyse des entrées de ligne de commande.
La System.CommandLine bibliothèque offre plusieurs avantages clés :
- Génération et validation automatiques du texte d’aide.
- Prise en charge des conventions de ligne de commande POSIX et Windows.
- Fonctionnalités d’achèvement des onglets intégrées.
- Comportement d’analyse cohérent entre les applications.
Ajoutez le
System.CommandLinepackage. Ajoutez cette directive après la directive de package existante :#:package System.CommandLine@2.0.0Important
La version
2.0.0était la dernière version lorsque ce didacticiel a été mis à jour pour la dernière fois. S’il existe une version plus récente disponible, utilisez la dernière version pour vous assurer que vous disposez des derniers packages de sécurité. Consultez la page NuGet du package pour connaître la dernière version pour vous assurer d’utiliser une version de package avec les derniers correctifs de sécurité.Ajoutez les instructions using nécessaires en haut de votre fichier (après les directives et
#!les#:packagedirectives) :using System.CommandLine; using System.CommandLine.Parsing;Définissez l’option de délai et l’argument messages. Ajoutez le code suivant pour créer les objets et
CommandLine.Optionl’optionCommandLine.Argumentde ligne de commande et l’argument :Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds.", DefaultValueFactory = parseResult => 100 }; Argument<string[]> messagesArgument = new("Messages") { Description = "Text to render." };Dans les applications en ligne de commande, les options commencent généralement par
--(tiret double) et peuvent accepter des arguments. L’option--delayaccepte un argument entier qui spécifie le délai en millisecondes. DéfinitmessagesArgumentla façon dont les jetons restants après l’analyse des options sont analysés en tant que texte. Chaque jeton devient une chaîne distincte dans le tableau, mais le texte peut être entre guillemets pour inclure plusieurs mots dans un seul jeton. Par exemple,"This is one message"devient un seul jeton, tandis qu’ilThis is four tokensdevient quatre jetons distincts.Le code précédent définit le type d’argument de l’option
--delayet que les arguments sont un tableau destringvaleurs. Cette application n’a qu’une seule commande. Vous utilisez donc la commande racine.Créez une commande racine et configurez-la avec l’option et l’argument. Ajoutez l’argument et l’option à la commande racine :
RootCommand rootCommand = new("Ascii Art file-based program sample"); rootCommand.Options.Add(delayOption); rootCommand.Arguments.Add(messagesArgument);Ajoutez le code pour analyser les arguments de ligne de commande et gérer les erreurs. Ce code valide les arguments de ligne de commande et stocke les arguments analysés dans l’objet 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; }
Le code précédent valide tous les arguments de ligne de commande. Si la validation échoue, les erreurs sont écrites dans la console et l’application se ferme.
Utiliser les résultats de la ligne de commande analysée
À présent, terminez l’application pour utiliser les options analysées et écrivez la sortie. Tout d’abord, définissez un enregistrement pour contenir les options analysées. Les applications basées sur des fichiers peuvent inclure des déclarations de type, telles que des enregistrements et des classes. Elles doivent être après toutes les instructions de niveau supérieur et toutes les fonctions locales.
Ajoutez une
recorddéclaration pour stocker les messages et la valeur de l’option de délai :public record AsciiMessageOptions(string[] Messages, int Delay);Ajoutez la fonction locale suivante avant la déclaration d’enregistrement. Cette méthode gère à la fois les arguments de ligne de commande et l’entrée standard, et retourne une nouvelle instance d’enregistrement :
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); }Créez une fonction locale pour écrire l’art ASCII avec le délai spécifié. Cette fonction écrit chaque message dans l’enregistrement avec le délai spécifié entre chaque message :
async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Remplacez la
ifclause que vous avez écrite précédemment par le code suivant qui traite les arguments de ligne de commande et écrivez la sortie :var parsedArgs = await ProcessParseResults(result); await WriteAsciiArt(parsedArgs); return 0;
Vous avez créé un type qui fournit une record structure aux options et arguments de ligne de commande analysés. Les nouvelles fonctions locales créent une instance de l’enregistrement et utilisent l’enregistrement pour écrire la sortie d’art ASCII.
Tester l’application finale
Testez l’application en exécutant plusieurs commandes différentes. Si vous rencontrez des problèmes, voici l’exemple terminé à comparer à ce que vous avez créé :
#!/usr/local/share/dotnet/dotnet run
#: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);
Dans ce tutoriel, vous avez appris à créer un programme basé sur des fichiers, où vous générez le programme dans un seul fichier C#. Ces programmes n’utilisent pas de fichier projet et peuvent utiliser la directive sur les #! systèmes unix. Les apprenants peuvent créer ces programmes après avoir essayé nos didacticiels en ligne et avant de créer des applications basées sur des projets plus volumineuses. Les applications basées sur des fichiers sont également une plateforme idéale pour les utilitaires de ligne de commande.