diff --git a/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp b/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp
index 17bf57c128dabcb28793fa0bf831150929624abd..62bef5b26db192d9c48117d220d0e1b08d1d0401 100644
--- a/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp
+++ b/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp
@@ -79,7 +79,7 @@ void export_DistributedMeshWriter( py::module & m, const char* name )
             py::arg("array"), py::arg("name"), py::arg("numberOfComponents") = 1)
         // NOTE: only the overload intended for sequential writing is exported, because we don't
         // have type casters for MPI_Comm (ideally, it would be compatible with the mpi4py objects)
-        .def("addPiece", static_cast< std::string (Writer::*)(const TNL::String&, unsigned) >( &Writer::addPiece ),
+        .def("addPiece", static_cast< std::string (Writer::*)(const std::string&, unsigned) >( &Writer::addPiece ),
               py::arg("mainFileName"), py::arg("subdomainIndex"))
     ;
 }
diff --git a/src/TNL/Meshes/Writers/PVTIWriter.h b/src/TNL/Meshes/Writers/PVTIWriter.h
index 4f391b142e972267eb67bad9415121c7e44c0e17..c37d40a5861b8e9f6f879d6af94d938c8d7fd3ba 100644
--- a/src/TNL/Meshes/Writers/PVTIWriter.h
+++ b/src/TNL/Meshes/Writers/PVTIWriter.h
@@ -57,27 +57,27 @@ public:
                        const unsigned MinCommonVertices = 0 );
 
    template< typename ValueType >
-   void writePPointData( const String& name,
+   void writePPointData( const std::string& name,
                          const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePCellData( const String& name,
+   void writePCellData( const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePDataArray( const String& name,
+   void writePDataArray( const std::string& name,
                          const int numberOfComponents = 1 );
 
    // add a single piece and return its source path
    // (useful for sequential writing, e.g. from tnl-decompose-grid)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const unsigned subdomainIndex,
                          const typename Grid::CoordinatesType& globalBegin,
                          const typename Grid::CoordinatesType& globalEnd );
 
    // add all pieces and return the source path for the current rank
    // (useful for parallel writing)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const DistributedMeshes::DistributedMesh< Grid >& distributedMesh );
 
    ~PVTIWriter();
diff --git a/src/TNL/Meshes/Writers/PVTIWriter.hpp b/src/TNL/Meshes/Writers/PVTIWriter.hpp
index fd3d9bfeb0f71a5742dd97fe9cdd2b0d87c80f0e..e28b1eed811dc34ed6e49f94e014ef5c7b078bb9 100644
--- a/src/TNL/Meshes/Writers/PVTIWriter.hpp
+++ b/src/TNL/Meshes/Writers/PVTIWriter.hpp
@@ -125,7 +125,7 @@ PVTIWriter< Grid >::writeEntities( const Grid& grid,
 template< typename Grid >
    template< typename ValueType >
 void
-PVTIWriter< Grid >::writePPointData( const String& name,
+PVTIWriter< Grid >::writePPointData( const std::string& name,
                                      const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -137,7 +137,7 @@ PVTIWriter< Grid >::writePPointData( const String& name,
 template< typename Grid >
    template< typename ValueType >
 void
-PVTIWriter< Grid >::writePCellData( const String& name,
+PVTIWriter< Grid >::writePCellData( const std::string& name,
                                     const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -149,7 +149,7 @@ PVTIWriter< Grid >::writePCellData( const String& name,
 template< typename Grid >
    template< typename ValueType >
 void
-PVTIWriter< Grid >::writePDataArray( const String& name,
+PVTIWriter< Grid >::writePDataArray( const std::string& name,
                                      const int numberOfComponents )
 {
    if( numberOfComponents != 0 && numberOfComponents != 1 && numberOfComponents != 3 )
@@ -162,12 +162,17 @@ PVTIWriter< Grid >::writePDataArray( const String& name,
 
 template< typename Grid >
 std::string
-PVTIWriter< Grid >::addPiece( const String& mainFileName,
+PVTIWriter< Grid >::addPiece( const std::string& mainFileName,
                               const unsigned subdomainIndex,
                               const typename Grid::CoordinatesType& globalBegin,
                               const typename Grid::CoordinatesType& globalEnd )
 {
-   if( ! mainFileName.endsWith( ".pvti" ) )
+   namespace fs = std::experimental::filesystem;
+
+   // get the basename of the main file (filename without extension)
+   const fs::path mainPath = mainFileName;
+   const fs::path basename = mainPath.stem();
+   if( mainPath.extension() != ".pvti" )
       throw std::logic_error("The mainFileName parameter must be the name of the "
                              ".pvti file (i.e., it must have the .pvti suffix).");
 
@@ -183,12 +188,6 @@ PVTIWriter< Grid >::addPiece( const String& mainFileName,
    for( int j = Grid::getMeshDimension(); j < 3; j++ )
       extent << "0 0 ";
 
-   namespace fs = std::experimental::filesystem;
-
-   // get the basename of the main file (filename without extension)
-   const fs::path mainPath = mainFileName.getString();
-   const fs::path basename = mainPath.stem();
-
    // create subdirectory for subdomains
    const fs::path subdirectory = mainPath.parent_path() / basename;
    fs::create_directory( subdirectory );
@@ -204,7 +203,7 @@ PVTIWriter< Grid >::addPiece( const String& mainFileName,
 
 template< typename Grid >
 std::string
-PVTIWriter< Grid >::addPiece( const String& mainFileName,
+PVTIWriter< Grid >::addPiece( const std::string& mainFileName,
                               const DistributedMeshes::DistributedMesh< Grid >& distributedMesh )
 {
    const MPI_Comm communicator = distributedMesh.getCommunicator();
diff --git a/src/TNL/Meshes/Writers/PVTUWriter.h b/src/TNL/Meshes/Writers/PVTUWriter.h
index 6d76781ff7ae68b33c05111186ae1276799b09ae..d53b5aa82ef7a4128336450c8ff4996aa2f180f7 100644
--- a/src/TNL/Meshes/Writers/PVTUWriter.h
+++ b/src/TNL/Meshes/Writers/PVTUWriter.h
@@ -45,25 +45,25 @@ public:
                        const unsigned MinCommonVertices = 0 );
 
    template< typename ValueType >
-   void writePPointData( const String& name,
+   void writePPointData( const std::string& name,
                          const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePCellData( const String& name,
+   void writePCellData( const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePDataArray( const String& name,
+   void writePDataArray( const std::string& name,
                          const int numberOfComponents = 1 );
 
    // add a single piece and return its source path
    // (useful for sequential writing, e.g. from tnl-decompose-mesh)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const unsigned subdomainIndex );
 
    // add all pieces and return the source path for the current rank
    // (useful for parallel writing)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const MPI_Comm communicator );
 
    ~PVTUWriter();
diff --git a/src/TNL/Meshes/Writers/PVTUWriter.hpp b/src/TNL/Meshes/Writers/PVTUWriter.hpp
index 03b1e9aee795f5d6dd792ff800ad2ed1084dffbb..004cccd96751f746d3b1a1e3de8fab265185891a 100644
--- a/src/TNL/Meshes/Writers/PVTUWriter.hpp
+++ b/src/TNL/Meshes/Writers/PVTUWriter.hpp
@@ -69,7 +69,7 @@ PVTUWriter< Mesh >::writeEntities( const Mesh& mesh,
 template< typename Mesh >
    template< typename ValueType >
 void
-PVTUWriter< Mesh >::writePPointData( const String& name,
+PVTUWriter< Mesh >::writePPointData( const std::string& name,
                                      const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -81,7 +81,7 @@ PVTUWriter< Mesh >::writePPointData( const String& name,
 template< typename Mesh >
    template< typename ValueType >
 void
-PVTUWriter< Mesh >::writePCellData( const String& name,
+PVTUWriter< Mesh >::writePCellData( const std::string& name,
                                     const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -93,7 +93,7 @@ PVTUWriter< Mesh >::writePCellData( const String& name,
 template< typename Mesh >
    template< typename ValueType >
 void
-PVTUWriter< Mesh >::writePDataArray( const String& name,
+PVTUWriter< Mesh >::writePDataArray( const std::string& name,
                                      const int numberOfComponents )
 {
    if( numberOfComponents != 0 && numberOfComponents != 1 && numberOfComponents != 3 )
@@ -106,10 +106,15 @@ PVTUWriter< Mesh >::writePDataArray( const String& name,
 
 template< typename Mesh >
 std::string
-PVTUWriter< Mesh >::addPiece( const String& mainFileName,
+PVTUWriter< Mesh >::addPiece( const std::string& mainFileName,
                               const unsigned subdomainIndex )
 {
-   if( ! mainFileName.endsWith( ".pvtu" ) )
+   namespace fs = std::experimental::filesystem;
+
+   // get the basename of the main file (filename without extension)
+   const fs::path mainPath = mainFileName;
+   const fs::path basename = mainPath.stem();
+   if( mainPath.extension() != ".pvtu" )
       throw std::logic_error("The mainFileName parameter must be the name of the "
                              ".pvtu file (i.e., it must have the .pvtu suffix).");
 
@@ -117,12 +122,6 @@ PVTUWriter< Mesh >::addPiece( const String& mainFileName,
    closePCellData();
    closePPointData();
 
-   namespace fs = std::experimental::filesystem;
-
-   // get the basename of the main file (filename without extension)
-   const fs::path mainPath = mainFileName.getString();
-   const fs::path basename = mainPath.stem();
-
    // create subdirectory for subdomains
    const fs::path subdirectory = mainPath.parent_path() / basename;
    fs::create_directory( subdirectory );
@@ -138,7 +137,7 @@ PVTUWriter< Mesh >::addPiece( const String& mainFileName,
 
 template< typename Mesh >
 std::string
-PVTUWriter< Mesh >::addPiece( const String& mainFileName,
+PVTUWriter< Mesh >::addPiece( const std::string& mainFileName,
                               const MPI_Comm communicator )
 {
    std::string source;
diff --git a/src/TNL/Meshes/Writers/VTIWriter.h b/src/TNL/Meshes/Writers/VTIWriter.h
index 8772205718c859a031a16c5f73c1d88020a49888..367fc96520824abc8d18d23d83e8beed695f4be0 100644
--- a/src/TNL/Meshes/Writers/VTIWriter.h
+++ b/src/TNL/Meshes/Writers/VTIWriter.h
@@ -12,6 +12,8 @@
 
 #pragma once
 
+#include <ostream>
+#include <sstream>
 #include <type_traits>
 
 #include <TNL/Meshes/VTKTraits.h>
@@ -54,17 +56,17 @@ public:
 
    template< typename Array >
    void writePointData( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeCellData( const Array& array,
-                       const String& name,
+                       const std::string& name,
                        const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeDataArray( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    ~VTIWriter();
diff --git a/src/TNL/Meshes/Writers/VTIWriter.hpp b/src/TNL/Meshes/Writers/VTIWriter.hpp
index 0744850d3e1a0760410a1dfad3394ba5cc37cbd2..9ea4684689eae86f01041349786e2e471c17b1b3 100644
--- a/src/TNL/Meshes/Writers/VTIWriter.hpp
+++ b/src/TNL/Meshes/Writers/VTIWriter.hpp
@@ -121,7 +121,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTIWriter< Mesh >::writePointData( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -137,7 +137,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTIWriter< Mesh >::writeCellData( const Array& array,
-                                  const String& name,
+                                  const std::string& name,
                                   const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -153,7 +153,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTIWriter< Mesh >::writeDataArray( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    // use a host buffer if direct access to the array elements is not possible
diff --git a/src/TNL/Meshes/Writers/VTKWriter.h b/src/TNL/Meshes/Writers/VTKWriter.h
index fbff5c6428c46eadce16cecce8901f1a7f003657..9308e0c86b79dc1f3e614249138a90d44288b067 100644
--- a/src/TNL/Meshes/Writers/VTKWriter.h
+++ b/src/TNL/Meshes/Writers/VTKWriter.h
@@ -10,6 +10,8 @@
 
 #pragma once
 
+#include <ostream>
+
 #include <TNL/Meshes/VTKTraits.h>
 
 namespace TNL {
@@ -57,17 +59,17 @@ public:
 
    template< typename Array >
    void writePointData( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeCellData( const Array& array,
-                       const String& name,
+                       const std::string& name,
                        const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeDataArray( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
 protected:
diff --git a/src/TNL/Meshes/Writers/VTKWriter.hpp b/src/TNL/Meshes/Writers/VTKWriter.hpp
index ada849aefc9b8726fcd8171e0d2de99dab328420..f2d46be863105a024db6d16801f98b9149ab53ff 100644
--- a/src/TNL/Meshes/Writers/VTKWriter.hpp
+++ b/src/TNL/Meshes/Writers/VTKWriter.hpp
@@ -456,7 +456,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTKWriter< Mesh >::writePointData( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    if( array.getSize() / numberOfComponents != typename Array::IndexType(pointsCount) )
@@ -480,7 +480,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTKWriter< Mesh >::writeCellData( const Array& array,
-                                  const String& name,
+                                  const std::string& name,
                                   const int numberOfComponents )
 {
    if( array.getSize() / numberOfComponents != typename Array::IndexType(cellsCount) )
@@ -504,7 +504,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTKWriter< Mesh >::writeDataArray( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    // use a host buffer if direct access to the array elements is not possible
diff --git a/src/TNL/Meshes/Writers/VTUWriter.h b/src/TNL/Meshes/Writers/VTUWriter.h
index 31a1175b8dfde2225fe3460ea6859a8af8bc90b7..7fe3c30c3976f3947813a5d682fb4b3adb23496d 100644
--- a/src/TNL/Meshes/Writers/VTUWriter.h
+++ b/src/TNL/Meshes/Writers/VTUWriter.h
@@ -12,6 +12,8 @@
 
 #pragma once
 
+#include <ostream>
+
 #include <TNL/Meshes/VTKTraits.h>
 
 namespace TNL {
@@ -52,17 +54,17 @@ public:
 
    template< typename Array >
    void writePointData( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeCellData( const Array& array,
-                       const String& name,
+                       const std::string& name,
                        const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeDataArray( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    ~VTUWriter();
diff --git a/src/TNL/Meshes/Writers/VTUWriter.hpp b/src/TNL/Meshes/Writers/VTUWriter.hpp
index 385537a521bc1d8a2cd0147ee27632d6849f39de..db6ba53ab94e7332b890e0b12958fedab9ec158c 100644
--- a/src/TNL/Meshes/Writers/VTUWriter.hpp
+++ b/src/TNL/Meshes/Writers/VTUWriter.hpp
@@ -432,7 +432,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTUWriter< Mesh >::writePointData( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -448,7 +448,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTUWriter< Mesh >::writeCellData( const Array& array,
-                                  const String& name,
+                                  const std::string& name,
                                   const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -464,7 +464,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTUWriter< Mesh >::writeDataArray( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    // use a host buffer if direct access to the array elements is not possible