C++ File I/O Writing files with non-standard locale settings


Example

If you need to write a file using different locale settings to the default, you can use std::locale and std::basic_ios::imbue() to do that for a specific file stream:

Guidance for use:

  • You should always apply a local to a stream before opening the file.
  • Once the stream has been imbued you should not change the locale.

Reasons for Restrictions: Imbuing a file stream with a locale has undefined behavior if the current locale is not state independent or not pointing at the beginning of the file.

UTF-8 streams (and others) are not state independent. Also a file stream with a UTF-8 locale may try and read the BOM marker from the file when it is opened; so just opening the file may read characters from the file and it will not be at the beginning.

#include <iostream>
#include <fstream>
#include <locale>

int main()
{
  std::cout << "User-preferred locale setting is "
            << std::locale("").name().c_str() << std::endl;

  // Write a floating-point value using the user's preferred locale.
  std::ofstream ofs1;
  ofs1.imbue(std::locale(""));
  ofs1.open("file1.txt");
  ofs1 << 78123.456 << std::endl;

  // Use a specific locale (names are system-dependent)
  std::ofstream ofs2;
  ofs2.imbue(std::locale("en_US.UTF-8"));
  ofs2.open("file2.txt");
  ofs2 << 78123.456 << std::endl;

  // Switch to the classic "C" locale
  std::ofstream ofs3;
  ofs3.imbue(std::locale::classic());
  ofs3.open("file3.txt");
  ofs3 << 78123.456 << std::endl;
}

Explicitly switching to the classic "C" locale is useful if your program uses a different default locale and you want to ensure a fixed standard for reading and writing files. With a "C" preferred locale, the example writes

78,123.456
78,123.456
78123.456

If, for example, the preferred locale is German and hence uses a different number format, the example writes

78 123,456
78,123.456
78123.456

(note the decimal comma in the first line).