LINUX.ORG.RU

fstream, wfstream, кодировка локали

 


0

2

Здравствуйте.

$ locale -a
C
POSIX
ru_RU
ru_RU.cp1251
ru_RU.koi8
ru_RU.utf8

// t.cpp
#include <fstream>
#include <iostream>
#include <locale>
using namespace std;

int main()
{
  if(true){
    wofstream f("wstream.utf8");
    f.imbue(locale("ru_RU.utf8"));
    f << L"ю";
  }

  if(true){
    wofstream f("wstream.koi8");
    f.imbue(locale("ru_RU.koi8"));
    f << L"ю";
  }

  if(true){
    ofstream f("fstream.utf8");
    f.imbue(locale("ru_RU.utf8"));
    f << "ю";
  }

  if(true){
    ofstream f("fstream.koi8");
    f.imbue(locale("ru_RU.koi8"));
    f << "ю";
  }
}

pavlick@pc ~/er $ g++ t.cpp
pavlick@pc ~/er $ ./a.out
pavlick@pc ~/er $ ls -l
итого 32
-rwxr-xr-x 1 pavlick pavlick 12224 сен 21 16:15 a.out
-rw-r--r-- 1 pavlick pavlick 2 сен 21 16:15 fstream.koi8
-rw-r--r-- 1 pavlick pavlick 2 сен 21 16:15 fstream.utf8
-rw-r--r-- 1 pavlick pavlick 1937 сен 21 16:10 t.cpp
-rw-r--r-- 1 pavlick pavlick 1 сен 21 16:15 wstream.koi8
-rw-r--r-- 1 pavlick pavlick 2 сен 21 16:15 wstream.utf8

Можно заметить, что смена кодировки локали в wostream меняет кодировку в выходном файле, чего не происходит с fostream.

С одной стороны логично - ведь нужно же как-то писать бинарные файлы, но с другой сторноы - можно было бы договориться об отсутствии конвертации при дефолтной «C» локали, а если я ставлю «ru_RU.koi8», то мне нужна именно она.

Но дело даже не в этом, а в том, что я не нашёл какого-то описания поведения fstream<char> при смене кодировки (листал стандарт, справочник). Может ли кто-то прояснить? Где написано, что fstream<char> никогда не меняет кодировку?

★★

Я щас ничего нового не открою, просто мысли напоследок. Похоже, что всё сводится к этой табличке:

std::codecvt<char, char, std::mbstate_t> 	identity conversion
std::codecvt<char16_t, char, std::mbstate_t> 	conversion between UTF-16 and UTF-8 (since C++11)
std::codecvt<char32_t, char, std::mbstate_t> 	conversion between UTF-32 and UTF-8 (since C++11)
std::codecvt<wchar_t, char, std::mbstate_t> 	conversion between the system's native wide and multibyte encodings (wchar_t <> кодировка локали)

char/narrow charter - общесистемный символьный тип/кодировка, все потоки (кроме wchar_t) кастуются к нему. wchar_t - доп бунус для конвертаций из/в кодировку локали. Одно только непонятно - зачем винда начала практиковать повсеместное использование wchar_t в своём апи, думали, что все должны под них подстроиться/написать стандарты? Следуя правильной идеологии, нужно было менять тип/кодировку char (ключик -std=c++98 char и апи одного типа, -std=c++11 уже другого).

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

зачем винда начала практиковать повсеместное использование wchar_t в своём апи

Для простой поддержки всех кодировок. Когда они это делали, то считали, что «UTF-16 хватит всем», вот они его и использовали со своим двухбайтовым wchar_t. А потом оказалось, что UTF-16 ни туда ни сюда, а менять уже поздно.

ключик -std=c++98 char и апи одного типа

char на особых правах в стандарте и используется для определения других типов и операций над типами, его размером вот так просто не повертишь.

xaizek ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.