Exploración del sistema de archivos
El encabezado <filesystem>
implementa la especificación técnica del sistema de archivos de C++ ISO/IEC TS 18822:2015 (borrador final: ISO/IEC JTC 1/SC 22/WG 21 N4100) y tiene tipos y funciones que le permiten escribir código independiente de la plataforma para navegar por el sistema de archivos. Al ser multiplataforma, contiene algunas API que no son de interés para los sistemas Windows. Por ejemplo, is_fifo(const path&)
siempre devuelve false
en Windows.
Información general
Use las API <filesystem>
para las siguientes tareas:
Iterar en los archivos y directorios que se encuentren bajo una ruta de acceso especificada.
Obtener información acerca de los archivos, incluidos la hora de creación, el tamaño, la extensión y el directorio raíz.
Componer, descomponer y comparar rutas de acceso.
Crear, copiar y eliminar directorios.
Copiar y eliminar archivos.
Para obtener más información sobre el E/S de archivo que utilice la biblioteca estándar, consulte Programación con iostream.
Rutas de acceso
Crear y componer rutas de acceso
Desde Windows XP las rutas de acceso de Windows se almacenan de forma nativa en Unicode. La clase path
realiza automáticamente todas las conversiones de cadenas necesarias. Acepta argumentos de matrices de caracteres anchos y estrechos, así como los tipos std::string
y std::wstring
con formato UTF8 o UTF16. La clase path
también normaliza automáticamente los separadores de ruta de acceso. Puede utilizar una sola barra diagonal como separador de directorios en los argumentos del constructor. Este separador le permite usar las mismas cadenas para almacenar rutas de acceso tanto en entornos Windows como UNIX:
path pathToDisplay(L"/FileSystemTest/SubDir3"); // OK!
path pathToDisplay2(L"\\FileSystemTest\\SubDir3"); // Still OK as always
path pathToDisplay3(LR"(\FileSystemTest\SubDir3)"); // Raw string literals are OK, too.
Para concatenar dos rutas de acceso, puede usar los operadores sobrecargados /
y /=
, que son análogos a los operadores +
y +=
en std::string
y std::wstring
. El objeto path
facilitará de forma oportuna los separadores si usted no lo hace.
path myRoot("C:/FileSystemTest"); // no trailing separator, no problem!
myRoot /= path("SubDirRoot"); // C:/FileSystemTest/SubDirRoot
Examinar rutas de acceso
La clase path tiene varios métodos que devuelven información acerca de diversas partes de la propia ruta. Esta información es distinta de la información sobre la entidad del sistema de archivos a la que puede hacer referencia. Puede obtener, entre otros, la raíz, la ruta de acceso relativa, el nombre de archivo o la extensión de archivo. Puede iterar sobre un objeto de ruta de acceso para examinar todas las carpetas de la jerarquía. En el ejemplo siguiente se muestra cómo iterar a través de un objeto de ruta de acceso. También se muestra cómo recuperar información sobre sus partes.
// filesystem_path_example.cpp
// compile by using: /EHsc /W4 /permissive- /std:c++17 (or later)
#include <string>
#include <iostream>
#include <sstream>
#include <filesystem>
using namespace std;
using namespace std::filesystem;
wstring DisplayPathInfo()
{
// This path may or may not refer to an existing file. We are
// examining this path string, not file system objects.
path pathToDisplay(L"C:/FileSystemTest/SubDir3/SubDirLevel2/File2.txt ");
wostringstream wos;
int i = 0;
wos << L"Displaying path info for: " << pathToDisplay << endl;
for (path::iterator itr = pathToDisplay.begin(); itr != pathToDisplay.end(); ++itr)
{
wos << L"path part: " << i++ << L" = " << *itr << endl;
}
wos << L"root_name() = " << pathToDisplay.root_name() << endl
<< L"root_path() = " << pathToDisplay.root_path() << endl
<< L"relative_path() = " << pathToDisplay.relative_path() << endl
<< L"parent_path() = " << pathToDisplay.parent_path() << endl
<< L"filename() = " << pathToDisplay.filename() << endl
<< L"stem() = " << pathToDisplay.stem() << endl
<< L"extension() = " << pathToDisplay.extension() << endl;
return wos.str();
}
int main()
{
wcout << DisplayPathInfo() << endl;
// wcout << ComparePaths() << endl; // see following example
wcout << endl << L"Press Enter to exit" << endl;
wstring input;
getline(wcin, input);
}
El ejemplo produce esta salida:
Displaying path info for: C:\FileSystemTest\SubDir3\SubDirLevel2\File2.txt
path part: 0 = C:
path part: 1 = \
path part: 2 = FileSystemTest
path part: 3 = SubDir3
path part: 4 = SubDirLevel2
path part: 5 = File2.txt
root_name() = C:
root_path() = C:\
relative_path() = FileSystemTest\SubDir3\SubDirLevel2\File2.txt
parent_path() = C:\FileSystemTest\SubDir3\SubDirLevel2
filename() = File2.txt
stem() = File2
extension() = .txt
Comparar rutas de acceso
La clase path
sobrecarga los mismos operadores de comparación que std::string
y std::wstring
. Cuando se comparan dos rutas de acceso, se realiza una comparación de cadenas una vez que se han normalizado los separadores. Si falta una barra diagonal final (o barra diagonal inversa), no se agrega y eso afecta a la comparación. En el siguiente ejemplo se muestra cómo se comparan los valores de ruta de acceso:
wstring ComparePaths()
{
path p0(L"C:/Documents"); // no trailing separator
path p1(L"C:/Documents/"); // p0 < p1
path p2(L"C:/Documents/2013/"); // p1 < p2
path p3(L"C:/Documents/2013/Reports/"); // p2 < p3
path p4(L"C:/Documents/2014/"); // p3 < p4
path p5(L"D:/Documents/2013/Reports/"); // p4 < p5
wostringstream wos;
wos << boolalpha <<
p0.wstring() << L" < " << p1.wstring() << L": " << (p0 < p1) << endl <<
p1.wstring() << L" < " << p2.wstring() << L": " << (p1 < p2) << endl <<
p2.wstring() << L" < " << p3.wstring() << L": " << (p2 < p3) << endl <<
p3.wstring() << L" < " << p4.wstring() << L": " << (p3 < p4) << endl <<
p4.wstring() << L" < " << p5.wstring() << L": " << (p4 < p5) << endl;
return wos.str();
}
C:\Documents < C:\Documents\: true
C:\Documents\ < C:\Documents\2013\: true
C:\Documents\2013\ < C:\Documents\2013\Reports\: true
C:\Documents\2013\Reports\ < C:\Documents\2014\: true
C:\Documents\2014\ < D:\Documents\2013\Reports\: true
Para ejecutar este código, péguelo en el ejemplo anterior completo antes de main
y quite la marca de comentario de la línea que lo llama en main.
Convertir entre tipos de ruta de acceso y de cadena
Un objeto path
se puede convertir implícitamente a std::wstring
o std::string
. Esto significa que puede pasar una ruta de acceso a funciones, como wofstream::open
, como se muestra en este ejemplo:
// filesystem_path_conversion.cpp
// compile by using: /EHsc /W4 /permissive- /std:c++17 (or later)
#include <string>
#include <iostream>
#include <fstream>
#include <filesystem>
using namespace std;
using namespace std::filesystem;
int main()
{
const wchar_t* p{ L"C:/Users/Public/Documents" };
path filePath(p);
filePath /= L"NewFile.txt";
// Open, write to, and close the file.
wofstream writeFile(filePath, ios::out); // implicit conversion
writeFile << L"Lorem ipsum\nDolor sit amet";
writeFile.close();
// Open, read, and close the file.
wifstream readFile;
wstring line;
readFile.open(filePath); // implicit conversions
wcout << L"File " << filePath << L" contains:" << endl;
while (readFile.good())
{
getline(readFile, line);
wcout << line << endl;
}
readFile.close();
wcout << endl << L"Press Enter to exit" << endl;
wstring input;
getline(wcin, input);
}
File C:\Users\Public\Documents\NewFile.txt contains:
Lorem ipsum
Dolor sit amet
Press Enter to exit
Iterar directorios y archivos
El encabezado <filesystem>
proporciona el tipo directory_iterator
para iterar a través de directorios individuales y la clase recursive_directory_iterator
para iterar de manera recursiva a través de un directorio y sus subdirectorios. Después de crear un iterador pasándole un objeto path
, el iterador apunta al primer elemento directory_entry de la ruta de acceso. Cree el iterador de fin llamando al constructor predeterminado.
Cuando se itera a través de un directorio, se puede encontrar con varios tipos de elementos. Estos elementos incluyen directorios, archivos, vínculos simbólicos y archivos de socket, entre otros. El objeto directory_iterator
devuelve sus elementos como objetos directory_entry
.