Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Aplicativos baseados em arquivo são programas contidos em um único *.cs arquivo que são criados e executados sem um arquivo de projeto (*.csproj) correspondente. Os aplicativos baseados em arquivos são ideais para aprender C# porque têm menos complexidade: todo o programa é armazenado em um único arquivo. Os aplicativos baseados em arquivo também são úteis para criar utilitários de linha de comando. Em plataformas Unix, aplicações baseadas em ficheiros podem ser executadas usando #!diretivas (shebang).
Neste tutorial, você:
- Crie um programa baseado em arquivo.
- Adicione suporte a Unix shebang (
#!). - Leia os argumentos da linha de comando.
- Manipule a entrada padrão.
- Escreva a saída de arte ASCII.
- Processar argumentos de linha de comando.
- Use resultados de linha de comando analisados.
- Teste a aplicação final.
Você cria um programa baseado em arquivo que escreve texto como arte ASCII. O aplicativo está contido em um único arquivo, usa pacotes NuGet que implementam alguns dos principais recursos.
Pré-requisitos
- O SDK do .NET 10. Transfira-o a partir do site de transferência do .NET.
- Código do Visual Studio. Baixe-o da página inicial do Visual Studio Code.
- (Opcional) A extensão C# DevKit para Visual Studio Code. Baixe-o do Visual Studio Code marketplace.
Criar um programa baseado em arquivo
Abra o Visual Studio Code e crie um novo arquivo chamado
AsciiArt.cs. Insira o seguinte texto:Console.WriteLine("Hello, world!");Salve o arquivo. Em seguida, abra o terminal integrado no Visual Studio Code e digite:
dotnet run AsciiArt.cs
Na primeira vez que você executa este programa, o host constrói o executável a partir do seu arquivo de origem, armazena dotnet artefatos de compilação em uma pasta temporária e, em seguida, executa o executável criado. Você pode verificar essa experiência digitando dotnet run AsciiArt.cs novamente. Desta vez, o dotnet host determina que o executável é atual e executa o executável sem criá-lo novamente. Você não vê nenhuma saída de compilação.
As etapas anteriores demonstram que os aplicativos baseados em arquivo não são arquivos de script. Eles são arquivos de origem C# que são criados usando um arquivo de projeto gerado em uma pasta temporária. Uma das linhas de saída exibidas quando você construiu o programa deve ter esta aparência (no Windows):
AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll
Em plataformas unix, a pasta de saída é algo semelhante a:
AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll
Essa saída informa onde os arquivos temporários e as saídas de compilação são colocados. Ao longo deste tutorial, sempre que você editar o arquivo de origem, o dotnet host atualiza o executável antes que ele seja executado.
As aplicações baseadas em ficheiros são programas C# normais. A única limitação é que eles devem ser escritos em um arquivo de origem. Você pode usar instruções de nível superior ou um método clássico Main como ponto de entrada. Você pode declarar qualquer tipo: classes, interfaces e structs. Você pode estruturar os algoritmos em um programa baseado em arquivo da mesma forma que faria em qualquer programa C#. Você pode até mesmo declarar vários namespaces para organizar seu código. Se você achar que um programa baseado em arquivo está crescendo muito grande para um único arquivo, você pode convertê-lo em um programa baseado em projeto e dividir a fonte em vários arquivos. Os aplicativos baseados em arquivos são uma ótima ferramenta de prototipagem. Você pode começar a experimentar com sobrecarga mínima para provar conceitos e criar algoritmos.
Suporte a Unix shebang (#!)
Observação
O suporte para #! diretivas aplica-se apenas em plataformas unix. Não há uma diretiva semelhante para o Windows executar diretamente um programa em C#. No Windows, você deve usar dotnet run na linha de comando.
No unix, você pode executar aplicativos baseados em arquivo diretamente, digitando o nome do arquivo de origem na linha de comando em vez de dotnet run. Você precisa fazer duas alterações:
Defina permissões de execução no arquivo de origem:
chmod +x AsciiArt.csAdicione uma diretiva shebang (
#!) como a primeira linha doAsciiArt.csarquivo:#!/usr/local/share/dotnet/dotnet run
A localização do dotnet pode ser diferente em diferentes instalações unix. Use o comando which dotnet para localizar o dotnet hospedeiro no seu ambiente.
Alternativamente, pode usar #!/usr/bin/env dotnet para resolver automaticamente o caminho dotnet a partir da variável de ambiente PATH:
#!/usr/bin/env dotnet
Depois de fazer essas duas alterações, você pode executar o programa diretamente da linha de comando:
./AsciiArt.cs
Se preferir, você pode remover a extensão para poder digitar ./AsciiArt . Pode adicionar o ao ficheiro de origem mesmo que utilize o #! Windows. A linha de comando do Windows não suporta #!, mas o compilador C# permite essa diretiva em aplicativos baseados em arquivos em todas as plataformas.
Ler argumentos de linha de comando
Agora, escreva todos os argumentos na linha de comando para a saída.
Substitua o conteúdo atual do
AsciiArt.cspelo seguinte código:if (args.Length > 0) { string message = string.Join(' ', args); Console.WriteLine(message); }Você pode executar esta versão digitando o seguinte comando:
dotnet run AsciiArt.cs -- This is the command line.A
--opção indica que todos os seguintes argumentos de comando devem ser passados para o programa AsciiArt. Os argumentosThis is the command line.são passados como uma matriz de cadeias de caracteres, onde cada cadeia de caracteres é uma palavra:This,is,the,command, eline..
Esta versão demonstra estes novos conceitos:
- Os argumentos de linha de comando são passados para o programa usando a variável
argspredefinida . Aargsvariável é uma matriz de strings:string[]. Se o comprimento deargsé 0, isso significa que nenhum argumento foi fornecido. Caso contrário, cada palavra na lista de argumentos será armazenada na entrada correspondente na matriz. - O
string.Joinmétodo une várias cadeias de caracteres em uma única cadeia de caracteres, com o separador especificado. Neste caso, o separador é um espaço único. - Console.WriteLine Grava a cadeia de caracteres no console de saída padrão, seguido por uma nova linha.
Manipule a entrada padrão
Isso lida com argumentos de linha de comando corretamente. Agora, adicione o código para manipular a entrada de leitura da entrada padrão (stdin) em vez de argumentos de linha de comando.
Adicione a seguinte
elsecláusula àifinstrução adicionada no código anterior:else { while (Console.ReadLine() is string line && line.Length > 0) { Console.WriteLine(line); } }O código anterior lê a entrada do console até que uma linha em branco ou um
nullseja lido. (O Console.ReadLine método retornanullse o fluxo de entrada for fechado digitando ctrl+C.)Teste a leitura de entrada padrão criando um novo arquivo de texto na mesma pasta. Nomeie o arquivo
input.txte adicione as seguintes linhas:Hello from ... dotnet! You can create file-based apps in .NET 10 and C# 14 Have fun writing useful utilitiesMantenha as linhas curtas para que elas sejam formatadas corretamente quando você adicionar o recurso para usar a arte ASCII.
Execute o programa novamente.
Com bash:
cat input.txt | dotnet run AsciiArt.csOu, com o PowerShell:
Get-Content input.txt | dotnet run AsciiArt.cs
Agora seu programa pode aceitar argumentos de linha de comando ou entrada padrão.
Escrever saída de arte ASCII
Em seguida, adicione um pacote que suporte arte ASCII, Colorful.Console. Para adicionar um pacote a um programa baseado em arquivo, use a #:package diretiva .
Adicione a seguinte diretiva após a
#!diretiva no seu arquivo AsciiArt.cs:#:package Colorful.Console@1.2.15Importante
A versão
1.2.15era a versão mais recente doColorful.Consolepacote quando este tutorial foi atualizado pela última vez. Verifique a página NuGet do pacote para obter a versão mais recente para garantir que você use uma versão do pacote com as correções de segurança mais recentes.Altere as linhas que chamam
Console.WriteLinepara usar oColorful.Console.WriteAsciimétodo em vez disso:async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Execute o programa e você verá a saída de arte ASCII em vez de texto ecoado.
Opções de comando de processo
Em seguida, vamos adicionar análise de linha de comando. A versão atual escreve cada palavra como uma linha de saída diferente. Os argumentos de linha de comando que você adicionou suportam dois recursos:
Cite várias palavras que devem ser escritas em uma linha:
AsciiArt.cs "This is line one" "This is another line" "This is the last line"Adicione uma
--delayopção para pausar entre cada linha:AsciiArt.cs --delay 1000
Os usuários devem ser capazes de usar ambos os argumentos juntos.
A maioria dos aplicativos de linha de comando precisa analisar argumentos de linha de comando para lidar com opções, comandos e entrada do usuário de forma eficaz. A System.CommandLine biblioteca fornece recursos abrangentes para lidar com comandos, subcomandos, opções e argumentos, permitindo que você se concentre no que seu aplicativo faz em vez da mecânica de analisar a entrada da linha de comando.
A System.CommandLine biblioteca oferece vários benefícios principais:
- Geração e validação automática de texto de ajuda.
- Suporte para POSIX e convenções de linha de comando do Windows.
- Capacidades integradas de preenchimento de separadores.
- Comportamento de análise consistente entre aplicativos.
Adicione o
System.CommandLinepacote. Aditar esta diretiva após a diretiva pacote existente:#:package System.CommandLine@2.0.0Importante
A versão
2.0.0era a versão mais recente quando este tutorial foi atualizado pela última vez. Se houver uma versão mais recente disponível, use a versão mais recente para garantir que você tenha os pacotes de segurança mais recentes. Verifique a página NuGet do pacote para obter a versão mais recente para garantir que você use uma versão do pacote com as correções de segurança mais recentes.Adicione as instruções de utilização necessárias na parte superior do seu ficheiro (após as
#!diretivas e#:package):using System.CommandLine; using System.CommandLine.Parsing;Defina a opção de atraso e o argumento de mensagens. Adicione o seguinte código para criar os
CommandLine.Optionobjetos e para representar a opção deCommandLine.Argumentlinha de comando e o argumento:Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds.", DefaultValueFactory = parseResult => 100 }; Argument<string[]> messagesArgument = new("Messages") { Description = "Text to render." };Em aplicativos de linha de comando, as opções normalmente começam com
--(traço duplo) e podem aceitar argumentos. A--delayopção aceita um argumento inteiro que especifica o atraso em milissegundos. OmessagesArgumentdefine como quaisquer tokens restantes após as opções são analisados como texto. Cada token se torna uma cadeia de caracteres separada na matriz, mas o texto pode ser citado para incluir várias palavras em um token. Por exemplo,"This is one message"torna-se um único token, enquantoThis is four tokensse torna quatro tokens separados.O código anterior define o tipo de argumento para a
--delayopção e que os argumentos são uma matriz destringvalores. Este aplicativo tem apenas um comando, então você usa o comando root.Crie um comando raiz e configure-o com a opção e o argumento. Adicione o argumento e a opção ao comando raiz:
RootCommand rootCommand = new("Ascii Art file-based program sample"); rootCommand.Options.Add(delayOption); rootCommand.Arguments.Add(messagesArgument);Adicione o código para analisar os argumentos da linha de comando e manipular quaisquer erros. Esse código valida os argumentos da linha de comando e armazena System.CommandLine.ParseResult os argumentos analisados no objeto:
ParseResult result = rootCommand.Parse(args); foreach (ParseError parseError in result.Errors) { Console.Error.WriteLine(parseError.Message); } if (result.Errors.Count > 0) { return 1; }
O código anterior valida todos os argumentos de linha de comando. Se a validação falhar, os erros serão gravados no console e o aplicativo será encerrado.
Usar resultados de linha de comando analisados
Agora, termine o aplicativo para usar as opções analisadas e escreva a saída. Primeiro, defina um registro para armazenar as opções analisadas. Os aplicativos baseados em arquivo podem incluir declarações de tipo, como registros e classes. Devem ser, afinal, declarações de alto nível e funções locais.
Adicione uma
recorddeclaração para armazenar as mensagens e o valor da opção de atraso:public record AsciiMessageOptions(string[] Messages, int Delay);Adicione a seguinte função local antes da declaração de registro. Esse método manipula argumentos de linha de comando e entrada padrão e retorna uma nova instância de registro:
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); }Crie uma função local para escrever a arte ASCII com o atraso especificado. Esta função grava cada mensagem no registro com o atraso especificado entre cada mensagem:
async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Substitua a
ifcláusula que você escreveu anteriormente pelo código a seguir que processa os argumentos da linha de comando e grava a saída:var parsedArgs = await ProcessParseResults(result); await WriteAsciiArt(parsedArgs); return 0;
Você criou um record tipo que fornece estrutura para as opções de linha de comando analisadas e argumentos. Novas funções locais criam uma instância do registro e usam o registro para gravar a saída de arte ASCII.
Testar a aplicação final
Teste o aplicativo executando vários comandos diferentes. Se você tiver problemas, aqui está o exemplo concluído para comparar com o que você criou:
#!/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);
Neste tutorial, você aprendeu a criar um programa baseado em arquivo, onde você cria o programa em um único arquivo C#. Esses programas não usam um arquivo de projeto e podem usar a #! diretiva em sistemas unix. Os alunos podem criar esses programas depois de experimentar nossos tutoriais on-line e antes de criar aplicativos maiores baseados em projetos. Os aplicativos baseados em arquivos também são uma ótima plataforma para utilitários de linha de comando.