System.IO.Path es una clase estática para manipular cadenas que representan rutas de archivos y directorios.
Cuando trabajamos con archivos (System.IO), muchos errores no vienen de leer o escribir el disco, sino de construir mal las rutas donde están esos archivos.
Que si barras invertidas \ en Windows, que si barras normales / en Linux, que si me falta un punto, que si la ruta es relativa… Es un campo de minas.
Para evitar que nuestro código sea frágil, esta clase nos da herramientas para combinar, separar y normalizar rutas sin pelear con barras, extensiones y directorios.
Recuerda: La clase Path NO accede al disco. No comprueba si el archivo existe. Solo manipula el texto de la ruta (Strings) de forma inteligente.
El problema con los separadores
Un error bastante típico es escribir rutas “a mano” ("C:\MisArchivos\datos.txt"). Esto es un problema porque Windows usa \ y Linux/Mac usan /. Si haces eso, tu aplicación fallará en Docker o en un servidor Linux.
// ❌ ERROR: Esto solo funciona bien en Windows
string ruta = "C:\\MisDocumentos\\" + nombreArchivo;
Si ejecutas ese código en un contenedor Docker (Linux) o en un Mac, es muy probable que falle o cree archivos con nombres extraños, porque Linux espera /.
La clase Path resuelve esto dándonos una constante del propio sistema: Path.DirectorySeparatorChar.
Console.WriteLine($"El separador de tu sistema es: '{Path.DirectorySeparatorChar}'");
// En Windows imprimirá: '\'
// En Linux imprimirá: '/'
Combinar rutas (Path.Combine)
Esta es una de las funciones más importante de toda la clase. En lugar de concatenar strings con +, usamos Path.Combine. Este método se encarga de poner (o quitar) los separadores necesarios automáticamente.
string carpeta = "Usuarios";
string subcarpeta = "Datos";
string archivo = "config.json";
// ✅ FORMA CORRECTA
string rutaCompleta = Path.Combine(carpeta, subcarpeta, archivo);
// Resultado (Windows): "Usuarios\Datos\config.json"
// Resultado (Linux): "Usuarios/Datos/config.json"
Si uno de los argumentos de Path.Combine empieza por una raíz (ej: "C:\Datos" o "/home"), Combine reiniciará la ruta desde ahí e ignorará todo lo anterior.
// Cuidado aquí:
string ruta = Path.Combine("C:\\Proyectos", "C:\\Drivers", "archivo.txt");
// Resultado: "C:\Drivers\archivo.txt" (Se ha comido "Proyectos")Path.Join, la alternativa moderna
También tenemos Path.Join. Es muy similar a Combine, pero no reinicia la ruta cuando encuentra un segmento con raíz. Simplemente une las piezas y puede ser útil en bucles donde quieres reducir asignaciones.
Analizar una ruta
A menudo recibimos una ruta completa (ej: C:\Fotos\2023\vacaciones.jpg) y necesitamos extraer solo una parte. Path tiene métodos para diseccionar este string quirúrgicamente.
Supongamos la ruta: string ruta = @"C:\Trabajo\Reporte.pdf";
| Método | Descripción | Resultado |
|---|---|---|
GetFileName(ruta) | Nombre completo | "Reporte.pdf" |
GetFileNameWithoutExtension(ruta) | Solo nombre | "Reporte" |
GetExtension(ruta) | Solo extensión | ".pdf" |
GetDirectoryName(ruta) | Carpeta contenedora | "C:\Trabajo" |
GetPathRoot(ruta) | Raíz del disco | "C:\" |
GetExtension es muy útil para filtrar archivos. Recuerda que incluye el punto (ej: .pdf).
Modificar rutas
A veces no queremos leer una ruta, sino transformarla. Por ejemplo, si queremos cambiar la extensión de un archivo para guardarlo en otro formato.
ChangeExtension
Cambia la extensión de una ruta (o la añade si no tiene).
string archivo = "imagen.bmp";
string nuevoArchivo = Path.ChangeExtension(archivo, ".png");
// Resultado: "imagen.png"
Esto no convierte la imagen. Solo cambia el texto de la ruta. Luego tú tendrás que hacer la conversión real del archivo.
Rutas absolutas y relativas
Cuando ejecutamos un programa, a veces usamos rutas relativas como "./config/app.json".
Para saber dónde está eso realmente en el disco duro, usamos GetFullPath.
string relativa = "datos.txt";
string absoluta = Path.GetFullPath(relativa);
// Resultado: "C:\Users\Luis\Proyectos\MiApp\bin\Debug\net8.0\datos.txt"
Este método resuelve los . (directorio actual) y los .. (directorio padre) automáticamente.
Archivos temporales y aleatorios
¿Necesitas guardar un archivo temporalmente y no te importa el nombre? Path te ayuda a no inventar la rueda.
GetTempPath(): Devuelve la carpeta de temporales del usuario actual (%TEMP%en Windows,/tmp/en Linux).GetTempFileName(): Crea un archivo físico vacío en la carpeta temporal y te devuelve su ruta completa.GetRandomFileName(): Devuelve un string aleatorio (tipou45w12qa.txt) criptográficamente fuerte, pero no crea el archivo.
// Ejemplo: Crear un archivo temporal para procesar datos
string archivoTemp = Path.GetTempFileName();
// Hacemos cosas...
File.WriteAllText(archivoTemp, "Datos temporales");
// Borramos al terminar
File.Delete(archivoTemp);
Caracteres inválidos
Si permites que un usuario escriba el nombre de un archivo, no des por válida la entrada. Puede contener caracteres prohibidos como :, *, ? o <.
Para sanear entradas, podemos usar GetInvalidFileNameChars():
char[] invalidos = Path.GetInvalidFileNameChars();
string nombreUsuario = "Informe:Final?.txt";
foreach (char c in invalidos)
{
if (nombreUsuario.Contains(c))
{
Console.WriteLine($"Caracter inválido detectado: {c}");
}
}