Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las aplicaciones basadas en archivos son programas contenidos en un único *.cs archivo que se compilan y ejecutan sin un archivo de proyecto (*.csproj) correspondiente. Las aplicaciones basadas en archivos son ideales para aprender C# porque tienen menos complejidad: todo el programa se almacena en un solo archivo. Las aplicaciones basadas en archivos también son útiles para crear utilidades de línea de comandos. En plataformas Unix, las aplicaciones basadas en archivos se pueden ejecutar mediante directivas
- Cree un programa basado en archivos.
- Agregue compatibilidad con Shebang (
#!) de Unix. - Lee los argumentos de la línea de comandos.
- Controle la entrada estándar.
- Escriba la salida de arte ASCII.
- Procesar argumentos de línea de comandos.
- Use los resultados de la línea de comandos analizados.
- Pruebe la aplicación final.
Crea un programa basado en archivos que escribe texto como arte ASCII. La aplicación está contenida en un único archivo, usa paquetes NuGet que implementan algunas de las características principales.
Prerrequisitos
- SDK de .NET 10. Descárguelo desde el sitio de descarga de .NET.
- Código de Visual Studio. Descárguelo desde la página principal de Visual Studio Code.
- (Opcional) La extensión DevKit de C# para Visual Studio Code. Descárguelo desde marketplace de Visual Studio Code.
Creación de un programa basado en archivos
Abra Visual Studio Code y cree un archivo denominado
AsciiArt.cs. Introduzca el texto siguiente:Console.WriteLine("Hello, world!");Guarde el archivo. A continuación, abra el terminal integrado en Visual Studio Code y escriba:
dotnet run AsciiArt.cs
La primera vez que ejecute este programa, el dotnet host compila el archivo ejecutable a partir del archivo de origen, almacena los artefactos de compilación en una carpeta temporal y, a continuación, ejecuta el ejecutable creado. Puede comprobar esta experiencia escribiendo dotnet run AsciiArt.cs de nuevo. Esta vez, el dotnet host determina que el ejecutable es actual y ejecuta el ejecutable sin volver a compilarlo. No ve ninguna salida de compilación.
Los pasos anteriores muestran que las aplicaciones basadas en archivos no son archivos de script. Son archivos de código fuente de C# que se compilan mediante un archivo de proyecto generado en una carpeta temporal. Una de las líneas de salida que se muestran al compilar el programa debe tener un aspecto similar al siguiente (en Windows):
AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll
En las plataformas unix, la carpeta de salida es algo similar a:
AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll
Esa salida indica dónde se colocan los archivos temporales y las salidas de compilación. En este tutorial, cada vez que edite el archivo de origen, el dotnet host actualiza el archivo ejecutable antes de que se ejecute.
Las aplicaciones basadas en archivos son programas de C# normales. La única limitación es que deben escribirse en un archivo de origen. Puede usar instrucciones de nivel superior o un método clásico Main como punto de entrada. Puede declarar cualquier tipo: clases, interfaces y estructuras. Puede estructurar los algoritmos en un programa basado en archivos igual que lo haría en cualquier programa de C#. Incluso puede declarar varios espacios de nombres para organizar el código. Si encuentra que un programa basado en archivos está creciendo demasiado grande para un solo archivo, puede convertirlo a un programa basado en proyectos y dividir el origen en varios archivos. Las aplicaciones basadas en archivos son una excelente herramienta de creación de prototipos. Puede empezar a experimentar con una sobrecarga mínima para probar conceptos y crear algoritmos.
Compatibilidad con Shebang (#!) de Unix
Nota:
La compatibilidad con #! directivas solo se aplica en plataformas unix. No hay una directiva similar para que Windows ejecute directamente un programa de C#. En Windows, debe usar dotnet run en la línea de comandos.
En unix, puede ejecutar aplicaciones basadas en archivos directamente, escribiendo el nombre del archivo de origen en la línea de comandos en lugar de dotnet run. Debe realizar dos cambios:
Establezca permisos de ejecución en el archivo de origen:
chmod +x AsciiArt.csAgregue una directiva shebang (
#!) como primera línea delAsciiArt.csarchivo:#!/usr/local/share/dotnet/dotnet run
La ubicación de dotnet puede ser diferente en diferentes instalaciones de Unix. Use el comando which dotnet para buscar el dotnet host en su entorno.
Como alternativa, puede usar #!/usr/bin/env dotnet para resolver automáticamente la ruta de dotnet desde la variable de entorno PATH.
#!/usr/bin/env dotnet
Después de realizar estos dos cambios, puede ejecutar el programa desde la línea de comandos directamente:
./AsciiArt.cs
Si lo prefiere, puede quitar la extensión para que pueda escribir ./AsciiArt en su lugar. Puede agregar al #! archivo de origen incluso si usa Windows. La línea de comandos de Windows no admite #!, pero el compilador de C# permite esa directiva en aplicaciones basadas en archivos en todas las plataformas.
Leer argumentos de la línea de comandos
Ahora, escriba todos los argumentos en la línea de comandos en la salida.
Reemplace el contenido actual de
AsciiArt.cspor el código siguiente:if (args.Length > 0) { string message = string.Join(' ', args); Console.WriteLine(message); }Para ejecutar esta versión, escriba el siguiente comando:
dotnet run AsciiArt.cs -- This is the command line.La
--opción indica que todos los argumentos de comando siguientes deben pasarse al programa AsciiArt. Los argumentosThis is the command line.se pasan como una matriz de cadenas, donde cada cadena es una palabra:This,is,the,commandyline..
En esta versión se muestran estos nuevos conceptos:
- Los argumentos de la línea de comandos se pasan al programa mediante la variable
argspredefinida . Laargsvariable es una matriz de cadenas:string[]. Si la longitud deargses 0, significa que no se proporcionó ningún argumento. De lo contrario, cada palabra de la lista de argumentos se almacena en la entrada correspondiente de la matriz. - El
string.Joinmétodo combina varias cadenas en una sola cadena, con el separador especificado. En este caso, el separador es un solo espacio. - Console.WriteLine escribe la cadena en la consola de salida estándar, seguida de una nueva línea.
Controlar la entrada estándar
Que controla correctamente los argumentos de la línea de comandos. Ahora, agregue el código para controlar la entrada de lectura de la entrada estándar (stdin) en lugar de los argumentos de la línea de comandos.
Agregue la cláusula siguiente
elsea laifinstrucción que agregó en el código anterior:else { while (Console.ReadLine() is string line && line.Length > 0) { Console.WriteLine(line); } }El código anterior lee la entrada de la consola hasta que se lee una línea en blanco o una
null. (El Console.ReadLine método devuelvenullsi la secuencia de entrada está cerrada escribiendo ctrl+C).Pruebe la lectura de la entrada estándar mediante la creación de un nuevo archivo de texto en la misma carpeta. Asigne al archivo el nombre
input.txty agregue las siguientes líneas:Hello from ... dotnet! You can create file-based apps in .NET 10 and C# 14 Have fun writing useful utilitiesMantenga las líneas cortas para que tengan el formato correcto al agregar la característica para usar el arte ASCII.
Vuelva a ejecutar el programa.
Con Bash:
cat input.txt | dotnet run AsciiArt.csO bien, con PowerShell:
Get-Content input.txt | dotnet run AsciiArt.cs
Ahora el programa puede aceptar argumentos de línea de comandos o entrada estándar.
Escritura de la salida de ASCII Art
A continuación, agregue un paquete que admita arte ASCII, Colorful.Console. Para agregar un paquete a un programa basado en archivos, use la #:package directiva .
Agregue la siguiente directiva después de la directiva en el
#!archivo AsciiArt.cs:#:package Colorful.Console@1.2.15Importante
La versión
1.2.15era la versión más reciente delColorful.Consolepaquete cuando este tutorial se actualizó por última vez. Compruebe la página NuGet del paquete para obtener la versión más reciente para asegurarse de que usa una versión del paquete con las correcciones de seguridad más recientes.Cambie las líneas que llaman
Console.WriteLinepara usar elColorful.Console.WriteAsciimétodo en su lugar:async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Ejecute el programa y verá la salida de arte ASCII en lugar de texto eco.
Opciones de comandos de proceso
A continuación, vamos a agregar análisis de línea de comandos. La versión actual escribe cada palabra como una línea de salida diferente. Los argumentos de la línea de comandos que ha agregado admiten dos características:
Cita varias palabras que se deben escribir en una sola línea:
AsciiArt.cs "This is line one" "This is another line" "This is the last line"Agregue una
--delayopción para pausar entre cada línea:AsciiArt.cs --delay 1000
Los usuarios deben poder usar ambos argumentos juntos.
La mayoría de las aplicaciones de línea de comandos deben analizar los argumentos de la línea de comandos para controlar las opciones, los comandos y la entrada del usuario de forma eficaz. La System.CommandLine biblioteca proporciona funcionalidades completas para controlar comandos, subcomandos, opciones y argumentos, lo que le permite concentrarse en lo que hace la aplicación en lugar de en la mecánica de analizar la entrada de la línea de comandos.
La System.CommandLine biblioteca ofrece varias ventajas clave:
- Generación y validación automáticas de texto de ayuda.
- Compatibilidad con convenciones de línea de comandos POSIX y Windows.
- Funcionalidades de finalización de pestañas integradas.
- Comportamiento de análisis coherente entre aplicaciones.
Agregue el
System.CommandLinepaquete. Agregue esta directiva después de la directiva de paquete existente:#:package System.CommandLine@2.0.0Importante
La versión
2.0.0era la versión más reciente cuando se actualizó por última vez este tutorial. Si hay una versión más reciente disponible, use la versión más reciente para asegurarse de que tiene los paquetes de seguridad más recientes. Compruebe la página NuGet del paquete para obtener la versión más reciente para asegurarse de que usa una versión del paquete con las correcciones de seguridad más recientes.Agregue las instrucciones using necesarias en la parte superior del archivo (después de las
#!directivas y#:package):using System.CommandLine; using System.CommandLine.Parsing;Defina la opción delay y el argumento messages. Agregue el código siguiente para crear los
CommandLine.Optionobjetos yCommandLine.Argumentpara representar la opción y el argumento de la línea de comandos:Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds.", DefaultValueFactory = parseResult => 100 }; Argument<string[]> messagesArgument = new("Messages") { Description = "Text to render." };En las aplicaciones de línea de comandos, las opciones suelen comenzar con
--(guión doble) y pueden aceptar argumentos. La--delayopción acepta un argumento entero que especifica el retraso en milisegundos.messagesArgumentDefine cómo se analizan como texto los tokens restantes después de que las opciones se analicen como texto. Cada token se convierte en una cadena independiente de la matriz, pero el texto se puede citar para incluir varias palabras en un token. Por ejemplo,"This is one message"se convierte en un solo token, mientrasThis is four tokensque se convierte en cuatro tokens independientes.El código anterior define el tipo de argumento para la
--delayopción y que los argumentos son una matriz destringvalores. Esta aplicación solo tiene un comando, por lo que se usa el comando raíz.Cree un comando raíz y configúrelo con la opción y el argumento . Agregue el argumento y la opción al comando raíz:
RootCommand rootCommand = new("Ascii Art file-based program sample"); rootCommand.Options.Add(delayOption); rootCommand.Arguments.Add(messagesArgument);Agregue el código para analizar los argumentos de la línea de comandos y controlar los errores. Este código valida los argumentos de la línea de comandos y almacena los argumentos analizados en el System.CommandLine.ParseResult objeto :
ParseResult result = rootCommand.Parse(args); foreach (ParseError parseError in result.Errors) { Console.Error.WriteLine(parseError.Message); } if (result.Errors.Count > 0) { return 1; }
El código anterior valida todos los argumentos de la línea de comandos. Si se produce un error en la validación, los errores se escriben en la consola y se cierra la aplicación.
Uso de los resultados de la línea de comandos analizados
Ahora, finalice la aplicación para usar las opciones analizadas y escribir la salida. En primer lugar, defina un registro para contener las opciones analizadas. Las aplicaciones basadas en archivos pueden incluir declaraciones de tipos, como registros y clases. Deben ser después de todas las instrucciones de nivel superior y las funciones locales.
Agregue una
recorddeclaración para almacenar los mensajes y el valor de la opción delay:public record AsciiMessageOptions(string[] Messages, int Delay);Agregue la siguiente función local antes de la declaración de registro. Este método controla los argumentos de la línea de comandos y la entrada estándar y devuelve una nueva instancia 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); }Cree una función local para escribir el arte ASCII con el retraso especificado. Esta función escribe cada mensaje en el registro con el retraso especificado entre cada mensaje:
async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Reemplace la
ifcláusula que escribió anteriormente por el código siguiente que procesa los argumentos de la línea de comandos y escribe la salida:var parsedArgs = await ProcessParseResults(result); await WriteAsciiArt(parsedArgs); return 0;
Ha creado un record tipo que proporciona estructura a las opciones y argumentos de la línea de comandos analizados. Las nuevas funciones locales crean una instancia del registro y usan el registro para escribir la salida de arte ASCII.
Prueba de la aplicación final
Pruebe la aplicación mediante la ejecución de varios comandos diferentes. Si tiene problemas, este es el ejemplo terminado para compararlo con lo que ha creado:
#!/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);
En este tutorial, ha aprendido a compilar un programa basado en archivos, donde se compila el programa en un único archivo de C#. Estos programas no usan un archivo de proyecto y pueden usar la #! directiva en sistemas unix. Los alumnos pueden crear estos programas después de probar nuestros tutoriales en línea y antes de compilar aplicaciones basadas en proyectos más grandes. Las aplicaciones basadas en archivos también son una excelente plataforma para las utilidades de la línea de comandos.