This really bugged me so I used the opportunity to learn a bit more about LibraryLink. I have to say that having a close look at the internals of Szabolcs' [LTemplate](http://community.wolfram.com/groups/-/m/t/575100) package was significantly more helpful than the actual LibraryLink documentation...

Setting up the C++ code:

    Needs["CCompilerDriver`"];
    Needs["GeneralUtilities`"];
    
    LibraryLink`BoilerPlate[funname_String] := 
     StringJoin["#include \"math.h\"
      
      #include \"WolframRTL.h\"
      
      static WolframCompileLibrary_Functions funStructCompile;
      
      static mbool initialize = 1;
      
      DLLEXPORT int Initialize_", funname, "(WolframLibraryData libData)
      {
      	if( initialize)
      	{
      		funStructCompile = libData->compileLibraryFunctions;
      		initialize = 0;
      	}
      	return 0;
      }
      
      DLLEXPORT void Uninitialize_", funname, "(WolframLibraryData libData)
      {
      	if( !initialize)
      	{
      		initialize = 1;
      	}
      }
      
      "]
    
    
    funname = "writeRealMatrixToFile";
    preamble = "
        #include <iostream>
        #include <fstream>
        #include <boost/lexical_cast.hpp>
        using namespace std;
        using namespace boost;
        ";
    
    code = StringJoin[preamble, "\n\n", LibraryLink`BoilerPlate[funname], 
       "extern \"C\" DLLEXPORT int ", funname, 
       "(WolframLibraryData libData, mint Argc, MArgument * Args, MArgument Res)
          {
           int err = 0;
              const char * file = MArgument_getUTF8String(Args[0]);
              const MTensor a0 = MArgument_getMTensor(Args[1]);
              const mreal * a = libData->MTensor_getRealData(a0);
              const char * prefix = MArgument_getUTF8String(Args[2]);
              const char * infix = MArgument_getUTF8String(Args[3]); 
              const char * suffix = MArgument_getUTF8String(Args[4]);
              const char * linesep = MArgument_getUTF8String(Args[5]);
       
              mint const* dims;
              dims = libData->MTensor_getDimensions(a0);
           mint i, j;
       
           ofstream outputstream;
       
           try
           {
               outputstream.open(file, ofstream::out | ofstream::app);
       
               for( i=0; i < (dims[0]-1); i++)
               {
                   outputstream << prefix;
                   for( j=0; j < dims[1]-1; j++)
                   {
                       outputstream << lexical_cast<string>(*a) << infix; \
    
                       a++;
                   }
                   outputstream << lexical_cast<string>(*a) << suffix;
                   a++;
                   outputstream << linesep;
               }
               {
                   outputstream << prefix;
                   for( j=0; j < dims[1]-1; j++)
                   {
                       outputstream << lexical_cast<string>(*a) << infix;
                       a++;
                   }
                   outputstream << lexical_cast<string>(*a) << suffix;
               }
       
               outputstream.close();
               MArgument_setInteger(Res, err);
           }
           catch (...)
           {
               return LIBRARY_FUNCTION_ERROR;
           }
       
           return LIBRARY_NO_ERROR;
          }
          "];

Creating the library in a temporary directory. (If you'd like to reuse the library, just specify a value of choice for `"TargetDirectory"`.) Since we require `boost` and it is not located at a path that can be found automatically by the compiler, I also specify `"IncludeDirectories"`. Of course you have to make sure that `boost` is installed on your system.

    libfile = CreateLibrary[code, funname,
       "Language" -> "C++",
       "TargetDirectory" -> $TemporaryDirectory,
       "IncludeDirectories" -> "/opt/local/include"
       ];

Loading the library function and creating a wrapper function as rudimentary user interface.

    If[TrueQ[Head[writeRealMatrixToFile] === LibraryFunction], 
      LibraryFunctionUnload[writeRealMatrixToFile]];
    ClearAll[writeRealMatrixToFile];
    If[TrueQ[FindLibrary[libfile] =!= $Failed],
      writeRealMatrixToFile = LibraryFunctionLoad[libfile, funname,
        {
         "UTF8String", {Real, 2, "Constant"}, "UTF8String", "UTF8String", 
         "UTF8String", "UTF8String"
         },
        Integer]
      ];
    
    Options[WriteRealMatrixToFile] = {
       "Prefix" -> "",
       "Infix" -> "\t",
       "Suffix" -> "",
       "RowSep" -> "\n"
       };
    WriteRealMatrixToFile[file_String, 
       A_?(MatrixQ[#, Developer`MachineRealQ] &), OptionsPattern[]] := 
      writeRealMatrixToFile[file, A,
       OptionValue["Prefix"],
       OptionValue["Infix"],
       OptionValue["Suffix"],
       OptionValue["RowSep"]
       ];

Running the test example.

    A = RandomReal[{-1, 1}, {1000, 1000}];
    file = "test.txt";
    Put[file];
    WriteRealMatrixToFile[file, A]; // AbsoluteTiming // First
    B = Import[file, "Table"]; // AbsoluteTiming // First
    Max[Abs[A - B]]

> 0.668737
> 
> 1.5853
> 
> 0.

This is over 20 times faster than using `Export` with `"Table"` as export format:

    Export["A.txt", A, "Table"]; // AbsoluteTiming // First

> 16.0703

Final remark:

I wrote `writeRealMatrixToFile` such that it appends to existing files (creating a new one if needed). This way, it can be used to export multiple data sets with other chunks of code in between. Typical file formats where this might be helpful are, e.g., povray and obj.

In particular, povray needs lists of vectors specified in the format `< x1, y1, z1 >,< x2, y2, z2 >,...` and to put `< ` and ` >` is the purpose of the `"Prefix"` and `"Suffix"` option. `"Infix"` specifies the column separator (e.g. `","`; default is a tabulator (`"\t"`)) and `"RowSep"` specifies the row seperators (default is newline (`"\n"`)).

Edit
---

New version employs `boost::lexical_cast`on the C++ side for conversion of `double` to `string`, preventing a loss of relative precision.