Re[7]: тысяча третий раз про Юникод
От: Кодт Россия  
Дата: 14.10.09 14:54
Оценка: 1 (1) :)
Здравствуйте, pepsicoca, Вы писали:

P>А wcout легко может (и должен) сделать ее юникодной. Просто по коду текущего Юникодного символа нужно делать imbue соответствующей локали.


Не надо ему ничего на лету подкручивать.
Всё, что ему нужно делать — это, наоборот, не заниматься трансляцией UTF-16 в байтовые кодировки — ни самому, ни нижележащим слоям CRT.
А обеспечить движение данных к функции WriteConsoleW вместо WriteFile или WriteConsoleA.

P>Тогда скажите, чем отличается std::wofstream от std::ofstream? В Вашей формулировке они не отличаются ничем. Тогда какой смысл иметь std::wofstream, если он ничем не отличатется от std::ofstream?


Он (точнее, не он сам, а putws — фасадом к которому он выступает) умеет доводить до вызовов WriteConsoleW. Но ты ему сперва в ножки поклонишься.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[7]: тысяча третий раз про Юникод
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 14.10.09 15:52
Оценка: 3 (1)
Здравствуйте, pepsicoca, Вы писали:
P>Тогда скажите, чем отличается std::wofstream от std::ofstream? В Вашей формулировке они не отличаются ничем. Тогда какой смысл иметь std::wofstream, если он ничем не отличатется от std::ofstream?

Смысл в том, чтобы открыть файл с содержанием "Hello World!!!" (в кодировке ASCII), и прочитать эту строчку в std::wstring с помощью std::wofstream, созданного без флага std::ios::binary, чтобы можно было потом отдать её (std::wstring строку) туда, где хотят wchar_t* текст. Т.е. если в софтине вы используете широкие строки, то пользуется std::wstring/std::wofstream/std::wifstream/std::wstringstream, если в софтине вы используете однобайтовые строки, то используете std::string/std::ofstream/std::ifstream/std::stringstream соответственно. При этом и std::ofstream и std::wofstream будет подразумевать, что в файле лежит однобайтовый текст, закодированный в активной системной локали, просто внутри программы они будут оперировать с разными символами char и wchar_t соответственно.

Как вы наверняка знаете, std::basic_ofstream/std::basic_ifstream могут работать в двух режимах: текстовом и бинарном. Это определяется отсутствием или наличием флага std::ios::binary соответственно. Текстовый режим работает по умолчанию. Бинарный включается руками во время конструирования или во время вызова метода open(). Если std::basic_ofstream работает в текстовом режиме, то он вправе изменять переданные строки перед сохранием, например он заменяет символ '\n' на последовательность символов "\r\n" на винде, на символ '\n' на Линуксе и на символ '\r' на маке. То же саме для std::basic_ifstream, только в обратную сторону. Если std::basic_ofstream работает в бинарном режиме, то он просто пишет то что ему дали и всё.

Текстовыми файлами являются файлы которые содержат данные в однобайтовой кодировке, например ASCII. Остальные файлы являются бинарными: то есть для их корректного чтения и правильного представления в памяти необходимы соответствующие алгоритмы. Если в файле хранится юникод-текст в кодировке UTF-8, то в самом начале файла лежит сигнатура, состоящая из байтов EF BB BF, если в кодировке UTF-16BE, то сигнатура — FE FF, если UTF-16LE — FF FE, если UTF-32BE или UTF-32LE, то 00 00 FE FF и FF FE 00 00. Так вот эти сигнатуры "говорят" нам: "мы не просто текстовые файлы, мы файлы с некими данными, хранящимися в определённом формате, и чтобы работать с этими данными, вам понадобятся определённые алгоритмы".

Чтобы прочитать простой текстовый файл программе, использующей char* строки, необходимо:
  • открыть этот файл с помощью std::ifstream
  • возможно, потребуется сделать вызов strm.unsetf(std::ios::skipws), чтобы не поскипать пробелы, табуляции, переходы строк и прочие пустые символы
  • читать оттуда строки и помещать их в char* контейнер, например в std::string

    Чтобы записать простой текстовый файл программе, использующей char* строки, необходимо:
  • открыть этот файл с помощью std::оfstream
  • писать туда строки из char* контейнеров, например из std::string

    Чтобы прочитать простой текстовый файл программе, использующей wchar_t* строки, необходимо:
  • открыть этот файл с помощью std::wifstream
  • возможно, потребуется сделать вызов strm.unsetf(std::ios::skipws), чтобы не поскипать пробелы, табуляции, переходы строк и прочие пустые символы
  • читать оттуда строки и помещать их в wchar_t* контейнер, например в std::wstring

    Чтобы записать простой текстовый файл программе, использующей wchar_t* строки, необходимо:
  • открыть этот файл с помощью std::wоfstream
  • писать туда строки из wchar_t* контейнеров, например из std::wstring

    Чтобы прочитать бинарный файл программе, не важно какие строки использующей, необходимо:
  • открыть этот файл с помощью std::ifstream, указав флаг std::ios::binary
  • hint: при этом не надо использовать std::wifstream для этих целей, потому что каждый байт файла будет помещён в wchar_t переменную, что логически не верно (я не знаю точно таким ли будет поведение std::wifstream, однако предпочитаю и советую использовать для бинарного чтения узкие потоковые классы)
  • не помню, надо ли здесь strm.unsetf(std::ios::skipws) делать :)
  • читать оттуда блоки данных и помещать их в char* контейнер
  • работать с этими данными

    Чтобы записать бинарный файл программе, не важно какие строки использующей, необходимо:
  • открыть этот файл с помощью std::оfstream, указав флаг std::ios::binary
  • hint: при этом не надо использовать std::wоfstream для этих целей, потому что каждое двубайтие будет впихнуто только в один байт при записи в файл, при этом будет происходить потеря старшего байта двубайтия (я не знаю точно таким ли будет поведение std::wоfstream, однако предпочитаю и советую использовать для бинарной записи узкие потоковые классы)
  • записать туда бинарные данные, взятые из char* контейнера

    Чтобы прочитать юникодный текстовый файл программе, использующей char* строки, необходимо:
  • открыть этот файл с помощью std::ifstream
  • узнать кодировку этого файла, используя хранящуююся в начале соответствующую сигнатуру (или если её там нет, то тогда софтина должна "знать" в какой unicode-кодировке ей подсунули текст, например она может спросить это у юзверя)
  • возможно, потребуется сделать вызов strm.unsetf(std::ios::skipws), чтобы не поскипать пробелы, табуляции, переходы строк и прочие пустые символы
  • читать оттуда строки и помещать их в char* контейнер, например в std::vector<[i]char*>[/i]
  • транслировать полученные данные из известной кодировки (UTF-8/UTF-16BE/UTF-16LE/etc.) в текстовую кодировку, с которой работает программа, например CP1251, при этом символы, эквивалента которых нет в целевой кодировке (например CP1251) будут заменены какой-то хернёй; результат поместить в в char* контейнер, например в std::string
  • работать с полученным однобайтовым текстом

    Чтобы записать юникодный текстовый файл программе, использующей char* строки, необходимо:
  • открыть этот файл с помощью std::оfstream
  • транслировать свои данные из кодировки, с которой работает программа, в нужную кодировку (UTF-8/UTF-16BE/UTF-16LE/etc.) и поместить результат в char* контейнер, например std::vector<[i]char*>[/i]
  • записать в начало файла сигнатуру нужной out кодировки (например для UTF-8 -> EF BB BF)
  • писать в файл данные из полученного char* контейнера, в котором хранится юникодный текст

    Чтобы прочитать юникодный текстовый файл программе, использующей wchar_t* строки, необходимо:
  • открыть этот файл с помощью std::ifstream
  • узнать кодировку этого файла, используя хранящуююся в начале соответствующую сигнатуру (или если её там нет, то тогда софтина должна "знать" в какой unicode-кодировке ей подсунули текст, например она может спросить это у юзверя)
  • возможно, потребуется сделать вызов strm.unsetf(std::ios::skipws), чтобы не поскипать пробелы, табуляции, переходы строк и прочие пустые символы
  • читать оттуда строки и помещать их в char* контейнер, например в std::vector<[i]char*>[/i]
  • транслировать полученные данные из известной кодировки (UTF-8/UTF-16BE/UTF-16LE/etc.) в текстовую кодировку, с которой работает программа, например USC-2 на винде позднее Windows NT или UTF-16LE на винде позднее Windows 2000, результат поместить в в wchar_t* контейнер, например в std::wstring
  • работать с полученным двубайтовым текстом

    Чтобы записать юникодный текстовый файл программе, использующей wchar_t* строки, необходимо:
  • открыть этот файл с помощью std::оfstream
  • транслировать свои wchar_t* строки из кодировки, с которой работает программа (например USC-2 на винде позднее Windows NT или UTF-16LE на винде позднее Windows 2000), в нужную кодировку (UTF-8/UTF-16BE/UTF-16LE/etc.) и поместить результат в char* контейнер, например std::vector<[i]char*>[/i]
  • записать в начало файла сигнатуру нужной out кодировки (например для UTF-16LE -> FF FE)
  • писать в файл данные из полученного char* контейнера, в котором хранится юникодный текст

    Для того чтобы и на входе (чтение unicode-текста из файлов), и на выходе (запись unicode-текста в файлы), и внутри алгоритмов программы поддержать не все возможные кодировки Юникода (UTF-8/UTF-16BE/UTF-16LE/etc.), а только лишь одну широкую кодировку (например нативную для винды — UTF-16LE), и при этом пользовать потоковые широкие классы, люди конфигурируют свои широкие потоковые классы с помощью фацетов и локалей, примерно как здесь: standard-file-streams-and-stdlocale_20.html или здесь: read-unicode-text-file-in-c.html. При этом, конечно, теряется вся гибкость работы с Unicode-кодировками, т.е. программа, использующая std::wstring и отконфигурированные std::wofstream и std::wifstream, и работающая на Windows 2000 and later, может писать и читать только в кодировке UTF-16LE, и если ей потребуется записать/почитать текст в другой unicode-кодировке (UTF-8/UTF-16BE/USC-2/UTF-32BE/UTF-32LE/etc.), то ей придётся заморочиться с пунктами, приведенными выше.

    Возврящаясь к нашим баранам. Т.е. к консоли. Если консоль — есть главное устройство ввода/вывода и интеракции с пользователем, как в GNU/Linux например, то ей по статусу положено быть навороченной, писать текст всеми цветами радуги, в локальной кодировке и в кодировках Юникода и пр. Если же консоль — аппендикс операционки, пережиток времён DOS'а, и главным устройством ввода/вывода и интеракции с пользователем является ГУЙ, как в винде например, тогда такой консоли по статусу не положено быть навороченной. Т.е. вы можете представить себе консоль, как простой текстовый файл, данные в котором хранятся в активной в системе локальной однобайтовой кодировке. У винды с русской локализацией (CP1251) консоль работает в кодировке DOS-866? чтобы поддержать всякой досовское старьё видимо. Соответственно для того чтобы std::wcout, который как мы знаем на винде с активной русской локалью CP1251 пишет текст в кодировке CP1251, для того чтобы std::wcout мог внятно по-русски написать в консоль, надо ему подсказать, что данные, которые ему заходят через оператор << в текстовой кодировке CP1251, в целевом файле (т.е. в консоли) должны сидеть в кодировке DOS-866, а не в кодировке CP1251, и это достигается вызовом std::wcout.imbue(std::locale("rus_rus.866"));. Вот в принципе и всё.


  • "Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
    unicode
    Re[8]: тысяча третий раз про Юникод
    От: Rakafon Украина http://rakafon.blogspot.com/
    Дата: 14.10.09 16:10
    Оценка:
    Здравствуйте, Rakafon, Вы писали:
    R>У винды с русской локализацией (CP1251) консоль работает в кодировке DOS-86. Чтобы поддержать всякой досовское старьё видимо. Соответственно для того чтобы std::wcout, который как мы знаем на винде с активной русской локалью CP1251 пишет текст в кодировке CP1251, для того чтобы std::wcout мог внятно по-русски написать в консоль, надо ему подсказать, что данные, которые ему заходят через оператор << в текстовой кодировке CP1251, в целевом файле (т.е. в консоли) должны сидеть в кодировке DOS-866, а не в кодировке CP1251, и это достигается вызовом std::wcout.imbue(std::locale("rus_rus.866"));.

    Тут ошибка, должно быть так:

    У винды с русской локализацией (CP1251) консоль работает в кодировке DOS-866. Чтобы поддержать всякой досовское старьё видимо.
    Все потоковые классы, в том числе и std::wcout, по умолчанию пишут в простой текстовый файл, в том числе и в консоль. Соответственно для того чтобы std::wcout, который как мы знаем на винде с активной русской локалью CP1251 пишет текст в кодировке CP1251, для того чтобы std::wcout мог внятно по-русски написать в консоль, надо ему подсказать, что данные, которые ему заходят через оператор << в текстовой кодировке UTF-16LE, в целевом файле (т.е. в консоли) должны сидеть не в кодировке CP1251 (как обычно), а в кодировке DOS-866, и это достигается вызовом [i]std::wcout.imbue(std::locale("rus_rus.866"));
    "Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
    Re[2]: тысяча третий раз про Юникод
    От: Sergey Chadov Россия  
    Дата: 14.10.09 17:39
    Оценка:
    Здравствуйте, andrey.desman, Вы писали:


    P>>2. Если в исходнике будет несколько сообщений "привет" на разных языках, то как транслятор сформирует Юникод для каждого из них? Откуда он узнает локаль текущего сообщения?


    AD>В исходнике не может быть нескольких сообщений на разных языках, потому что ты ограничен таблицей cp1251. Если конечно сам исходник не в юникоде записан. Правда я не знаю, поддерживает ли студия компиляцию юникодных исходников.


    поддерживает.
    --
    Sergey Chadov

    ... << RSDN@Home 1.2.0 alpha rev. 685>>
    Re[4]: тысяча третий раз про Юникод
    От: Sergey Chadov Россия  
    Дата: 14.10.09 17:39
    Оценка: +1
    Здравствуйте, Rakafon, Вы писали:


    R>Вы думаете щазз здесь появится разработчики виндовой консоли и разраюботчики std::cout/std::wcout из мелкософта и начнуть объяснять технически детали и причины нереализации таковой фичи. Я ж говорю: виндовая консоль — гавно! Сделайте свою консоль с нативной поддержкой Unicod'а и возможностью писать шрифтом "Georgia", "Gigi" или "Kunstler Script", и будет вам счастье!


    Консоль, как и вся остальная винда вполне юникодная. Только вот шрифт там по-умолчанию стоит неюникодный.
    --
    Sergey Chadov

    ... << RSDN@Home 1.2.0 alpha rev. 685>>
    Re: тысяча третий раз про Юникод
    От: _DAle_ Беларусь  
    Дата: 14.10.09 18:19
    Оценка:
    Здравствуйте, pepsicoca, Вы писали:

    P>3. Если в экзешнике уже лежит Юникодная строка, почему кириллица не печатается без явного указания локали функцией imbue? Ведь по Юникоду однозначно определяется начертание символа. И чтобы напечатать Юникод локаль не нужна.


    http://www.rsdn.ru/forum/cpp/645589.1.aspx
    Автор: MaximE
    Дата: 18.05.04


    P>Спасибо.
    Re[2]: тысяча третий раз про Юникод
    От: MasterZiv СССР  
    Дата: 14.10.09 19:00
    Оценка: -1
    jazzer пишет:

    > В качестве дикого предположения (я под винду не программирую)...

    > Ты ведь, наверное, имеешь в виду, что не печатает в терминале? Так он не
    > юникодный, скорее всего.

    Я ему это уже раза два писал. Видимо, бесполезно.
    Posted via RSDN NNTP Server 2.1 beta
    Re[3]: тысяча третий раз про Юникод
    От: MasterZiv СССР  
    Дата: 14.10.09 19:02
    Оценка: -2
    pepsicoca пишет:

    > Зная, что терминал не юникодный и зная, что нужно выводить кириллицу

    > (это можно узнать из Юникодного кода кирилических символов) почему бы
    > системе самой перед выводом кирилицы не сделать imbue той локали,
    > которая нужна?

    Потому что это винда. Там терминалы на фиг никому не нужны,
    только экзотам типа юниксоидов, пользующих cygwin или MinGW-Sys,
    но у них и свои консоли имеются. Кстати, в cygwin есть и юникодная,
    почему бы тебе ею не воспользоваться ?
    Posted via RSDN NNTP Server 2.1 beta
    Re[4]: тысяча третий раз про Юникод
    От: MasterZiv СССР  
    Дата: 14.10.09 19:09
    Оценка:
    Rakafon пишет:

    > Вы думаете щазз здесь появится разработчики виндовой консоли и

    > разраюботчики /std::cout///std::wcout/ из мелкософта и начнуть объяснять
    > технически детали и причины нереализации таковой фичи. Я ж говорю:
    > виндовая консоль — гавно! Сделайте свою консоль с нативной поддержкой
    > Unicod'а и возможностью писать шрифтом "Georgia", "Gigi" или "Kunstler
    > Script", и будет вам счастье!

    Главное, дело вовсе не в невозможности создать это чудо.
    В винде просто тупо не найдётся таких приложений, чтобы работали
    в этом режиме. Это ж надо ! Юникодное приложение, не оконное,
    а потоковое, и ещё что-то пишущее активно в консоль.

    FAR разве что ... Да он сам консолью правит.
    Posted via RSDN NNTP Server 2.1 beta
    Re[5]: тысяча третий раз про Юникод
    От: Cyberax Марс  
    Дата: 14.10.09 19:18
    Оценка:
    Здравствуйте, Кодт, Вы писали:

    К>И чтобы текстовый терминал в никсах тоже умел, и желательно без трюков с фреймбуфером, а прямо родным кодогенератором CGA-видяхи (со фреймбуфером он, кстати, умеет — только нужно бубен потолще выхватить).

    С KMS бубна уже не нужно.
    Sapienti sat!
    Re[3]: тысяча третий раз про Юникод
    От: IID Россия  
    Дата: 14.10.09 22:47
    Оценка:
    Здравствуйте, MasterZiv, Вы писали:

    MZ>jazzer пишет:


    >> В качестве дикого предположения (я под винду не программирую)...

    >> Ты ведь, наверное, имеешь в виду, что не печатает в терминале? Так он не
    >> юникодный, скорее всего.

    MZ>Я ему это уже раза два писал. Видимо, бесполезно.


    Консоль в винде уникодная. Но ты прав, бесполезно писать бред. Причём неважно сколько раз.
    kalsarikännit
    Re[3]: тысяча третий раз про Юникод
    От: jazzer Россия Skype: enerjazzer
    Дата: 15.10.09 02:41
    Оценка:
    Здравствуйте, Sergey, Вы писали:

    S>Заметно, что под винду не программируешь. С файлами в VC вообще жесткий прикол — они по умолчанию из широких строк в узкие конвертируют.


    жесть какая
    jazzer (Skype: enerjazzer) Ночная тема для RSDN
    Автор: jazzer
    Дата: 26.11.09

    You will always get what you always got
      If you always do  what you always did
    Re[8]: тысяча третий раз про Юникод
    От: pepsicoca  
    Дата: 15.10.09 06:55
    Оценка:
    Здравствуйте, Rakafon, Вы писали:

    Объем работы просто впечатляет.

    АднакА есть несколько возражений против нарисованной картины мира ввода-вывода.

    Нормальный человек ожидает, что std::fstream будет читать/писать из файла объекты char.
    Также нормальный человек ожидает, что std::wfstream будет читать/писать из файла объекты wchar_t.

    Опять же нормальный человек ожидает, что поведение этих потоков по отношению к char и wchar_t будет симметричным. То есть "побайтовое" чтение из std::fstream будет доставать из потока char за одно чтение, а "побайтовое" чтение из std::wfstream будет доставать из потока wchar_t за одно чтение.

    АднакА почему-то нестандартно мыслящие разработчики ввода-вывода сделали так, что "побайтовое" чтение из std::wfstream достает из широкого потока char за одно чтение.

    Может меня подводит мое чувство симметрии, но мне кажется, что это неправильно. И главное, непонятно, зачем это сделано. Если мне надо подергать файл побайтово, я всегда могу открыть его узким потоком и подергать его побайтово.

    С уважением...
    Re[4]: тысяча третий раз про Юникод
    От: _DAle_ Беларусь  
    Дата: 15.10.09 08:10
    Оценка:
    Здравствуйте, jazzer, Вы писали:

    J>Здравствуйте, Sergey, Вы писали:


    S>>Заметно, что под винду не программируешь. С файлами в VC вообще жесткий прикол — они по умолчанию из широких строк в узкие конвертируют.


    J>жесть какая


    Это не столько в VC, сколько в stl вообще.
    Re[5]: тысяча третий раз про Юникод
    От: Sergey Россия  
    Дата: 15.10.09 08:45
    Оценка:
    Здравствуйте, _DAle_, Вы писали:

    S>>>Заметно, что под винду не программируешь. С файлами в VC вообще жесткий прикол — они по умолчанию из широких строк в узкие конвертируют.


    J>>жесть какая


    _DA>Это не столько в VC, сколько в stl вообще.


    Насколько я знаю, в стандарте это вообще не регламентируется. Ну а под виндой лично я просто использую codecvt_null из бустовых архивов.
    Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
    Re[9]: тысяча третий раз про Юникод
    От: Rakafon Украина http://rakafon.blogspot.com/
    Дата: 15.10.09 08:56
    Оценка: -1
    Здравствуйте, pepsicoca, Вы писали:
    P>Нормальный человек ожидает, что std::fstream будет читать/писать из файла объекты char.
    P>Также нормальный человек ожидает, что std::wfstream будет читать/писать из файла объекты wchar_t.

    Нормальный человек ожидает, что с файловыми потоками можно работать либо в текстовом режиме, либо в бинарном.
    Если файловый поток работает в бинарном режиме, то на входе/выходе конфигурируют байтыю Именно байты, а не двубайтия или какие другие структуры данных. Именно поэтому нелогично использовать широкие потокы для бинарного доступа к файловому содержимому. Если файловый поток работает в текстовом режиме, то на выходе в файл и на входе из файла всегда конфигурируют символы, размер которых равен одному байту. Одному байту. Так устроены текстовые файлы. Если в файле "сидит", что-то другое, то это не текстовый файл, а файл с определённым образом закодированными данными со своей уникальной структурой, и значит такие данные надо выдирать из файла через бинарный доступ к нему. Файлы, в которых "сидит" текст, каждый символ которого занимает более байта, не являются текстовыми файлами.


    P>Опять же нормальный человек ожидает, что поведение этих потоков по отношению к char и wchar_t будет симметричным. То есть "побайтовое" чтение из std::fstream будет доставать из потока char за одно чтение, а "побайтовое" чтение из std::wfstream будет доставать из потока wchar_t за одно чтение.


    Нормальный человек ожидает, что работа с файлом будет происходить всегда единобразно: то есть побайтово! И по фиг при этом какие специализации потоковых классов std::basic_ofstream/std::basic_ifstream при этом используются! И если в файле располагаются не текстовые данные (а таковыми являются только мультибайтовые строки), то с файлом работают в бинарном режиме, доставая оттуда по байтику и конвертируя полученное добро в необходимое представление в памяти: то же саме касается и двубайтовых строк.


    P>АднакА почему-то нестандартно мыслящие разработчики ввода-вывода сделали так, что "побайтовое" чтение из std::wfstream достает из широкого потока char за одно чтение.


    Наоборот, так сделали разработчики со "стандартным" образом мышления, которые не нарушили концепцию, существующую ещё до нашей эры: древние египтяне тоже читали свои файлы побайтово! Когда потоковый класс работает с файлом, он работает с ним побайтово! И неважно во что он потом кастит каждый байт: в char, unsigned char, signed char, wchar_t, unsigned wchar_t, signed wchar_t, int, short int, long, etc. std::ifstream каждый байт кастит в char, std::wifstream каждый байт кастит в wchar_t. Если разработчик хочет, чтобы результат каждого чтения байта из файла был помещён в переменную, равную размеру байту, он использует std::ifstream. Если разработчик хочет нарушить существующую ещё с древнеегипетских времён концепцию: заставить потоковый класс читать сразу по два байта, в то время как его (потоковый класс) просят прочитать только один байт, он берёт std::wifstream и начинает издеваться над ним с помощью всякий фацетов. Иногда это оправдано. И если разработчику надо из фала вычитать unsigned int, значит ему надо sizeof(unsigned int) раз вычитать из фала по байтику и сложить это добро в переменную unsigned int, и воспользоваться при этом потоковым классом со стандартным поведением, который каждый раз вычитывая по байтику, будет результат складывать в переменную, равную по размерам байта.


    P>Может меня подводит мое чувство симметрии, но мне кажется, что это неправильно. И главное, непонятно, зачем это сделано. Если мне надо подергать файл побайтово, я всегда могу открыть его узким потоком и подергать его побайтово.


    Не знаю насчёт вашего чувства симметрии, но ИМХО: вы путаете тёплое с мягким: с файлами всегда работают побайтово.


    С Уважением.

    "Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
    unicode
    Re[3]: тысяча третий раз про Юникод
    От: alsemm Россия  
    Дата: 15.10.09 11:11
    Оценка:
    Здравствуйте, pepsicoca, Вы писали:

    P>Здравствуйте, K13, Вы писали:


    P>>>3. Если в экзешнике уже лежит Юникодная строка, почему кириллица не печатается без явного указания локали функцией imbue? Ведь по Юникоду однозначно определяется начертание символа. И чтобы напечатать Юникод локаль не нужна.


    K13>>потоки ввода-вывода работают с char. Без указания, какая именно кодировка является активной, не обойтись.


    P>Эта информация содержится в каждом коде Юникода. То есть по коду Юникода можно понять, какой это язык и слазить в систему за соответствующим начертанием символа в соответствующую таблицу.

    Что это за таблица такая волшебная?
    Re[10]: тысяча третий раз про Юникод
    От: pepsicoca  
    Дата: 15.10.09 12:11
    Оценка:
    Здравствуйте, Rakafon, Вы писали:

    R>Здравствуйте, pepsicoca, Вы писали:

    P>>Нормальный человек ожидает, что std::fstream будет читать/писать из файла объекты char.
    P>>Также нормальный человек ожидает, что std::wfstream будет читать/писать из файла объекты wchar_t.

    R>Нормальный человек ожидает, что с файловыми потоками можно работать либо в текстовом режиме, либо в бинарном.

    R>Если файловый поток работает в бинарном режиме, то на входе/выходе конфигурируют байтыю Именно байты, а не двубайтия или какие другие структуры данных. Именно поэтому нелогично использовать широкие потокы для бинарного доступа к файловому содержимому. Если файловый поток работает в текстовом режиме, то на выходе в файл и на входе из файла всегда конфигурируют символы, размер которых равен одному байту. Одному байту. Так устроены текстовые файлы. Если в файле "сидит", что-то другое, то это не текстовый файл, а файл с определённым образом закодированными данными со своей уникальной структурой, и значит такие данные надо выдирать из файла через бинарный доступ к нему. Файлы, в которых "сидит" текст, каждый символ которого занимает более байта, не являются текстовыми файлами.

    Так можно дойти до бита. Объявить бит единой и неделимой единицей информации (кстати, так оно и есть) и объявить, что файлы должны читаться побитно. А все, кто хочет строить какие-то более сложные структуры из файлов должны читать файл побитно и потом ручками эти структуры восстанавливать.

    P>>Опять же нормальный человек ожидает, что поведение этих потоков по отношению к char и wchar_t будет симметричным. То есть "побайтовое" чтение из std::fstream будет доставать из потока char за одно чтение, а "побайтовое" чтение из std::wfstream будет доставать из потока wchar_t за одно чтение.


    R>Нормальный человек ожидает, что работа с файлом будет происходить всегда единобразно: то есть побайтово! И по фиг при этом какие специализации потоковых классов std::basic_ofstream/std::basic_ifstream при этом используются! И если в файле располагаются не текстовые данные (а таковыми являются только мультибайтовые строки), то с файлом работают в бинарном режиме, доставая оттуда по байтику и конвертируя полученное добро в необходимое представление в памяти: то же саме касается и двубайтовых строк.



    P>>АднакА почему-то нестандартно мыслящие разработчики ввода-вывода сделали так, что "побайтовое" чтение из std::wfstream достает из широкого потока char за одно чтение.


    R>Наоборот, так сделали разработчики со "стандартным" образом мышления, которые не нарушили концепцию, существующую ещё до нашей эры: древние египтяне тоже читали свои файлы побайтово! Когда потоковый класс работает с файлом, он работает с ним побайтово! И неважно во что он потом кастит каждый байт: в char, unsigned char, signed char, wchar_t, unsigned wchar_t, signed wchar_t, int, short int, long, etc. std::ifstream каждый байт кастит в char, std::wifstream каждый байт кастит в wchar_t. Если разработчик хочет, чтобы результат каждого чтения байта из файла был помещён в переменную, равную размеру байту, он использует std::ifstream. Если разработчик хочет нарушить существующую ещё с древнеегипетских времён концепцию: заставить потоковый класс читать сразу по два байта, в то время как его (потоковый класс) просят прочитать только один байт, он берёт std::wifstream и начинает издеваться над ним с помощью всякий фацетов.


    И что, внутри фасцета я могу рекурсивно вызвать повторное чтение, чтобы считать дополнительный байт и уложить его во вторую половину wchar_t?

    R>Иногда это оправдано. И если разработчику надо из фала вычитать unsigned int, значит ему надо sizeof(unsigned int) раз вычитать из фала по байтику и сложить это добро в переменную unsigned int, и воспользоваться при этом потоковым классом со стандартным поведением, который каждый раз вычитывая по байтику, будет результат складывать в переменную, равную по размерам байта.



    P>>Может меня подводит мое чувство симметрии, но мне кажется, что это неправильно. И главное, непонятно, зачем это сделано. Если мне надо подергать файл побайтово, я всегда могу открыть его узким потоком и подергать его побайтово.


    R>Не знаю насчёт вашего чувства симметрии, но ИМХО: вы путаете тёплое с мягким: с файлами всегда работают побайтово.


    Плохая концепция. С байтовыми файлами надо работать побайтово. С файлами широких байтов надо работать "поширокобайтово". С файлами, в которые упакованы другие типы надо работать по единицам этих типов.

    И вообще, если пишут:

    typedef basic_ofstream<myType, char_traits<myType> > myTypeofstream;

    то единицей записи в таком файле должен быть не байт, а тип myType. А иначе весь смысл шаблонов теряется.


    R>С Уважением.


    R>
    Re[4]: тысяча третий раз про Юникод
    От: pepsicoca  
    Дата: 15.10.09 12:13
    Оценка:
    Здравствуйте, alsemm, Вы писали:

    A>Здравствуйте, pepsicoca, Вы писали:


    P>>Здравствуйте, K13, Вы писали:


    P>>>>3. Если в экзешнике уже лежит Юникодная строка, почему кириллица не печатается без явного указания локали функцией imbue? Ведь по Юникоду однозначно определяется начертание символа. И чтобы напечатать Юникод локаль не нужна.


    K13>>>потоки ввода-вывода работают с char. Без указания, какая именно кодировка является активной, не обойтись.


    P>>Эта информация содержится в каждом коде Юникода. То есть по коду Юникода можно понять, какой это язык и слазить в систему за соответствующим начертанием символа в соответствующую таблицу.

    A>Что это за таблица такая волшебная?

    Ну где там винда хранит начертание символов? В шрифтах наверное. Значит в шрифт.
    Re[5]: тысяча третий раз про Юникод
    От: Кодт Россия  
    Дата: 15.10.09 12:48
    Оценка:
    Здравствуйте, pepsicoca, Вы писали:

    P>Ну где там винда хранит начертание символов? В шрифтах наверное. Значит в шрифт.


    Плакать уже хочется, как мы плавно от STL и CRT перешли к шрифтовым движкам... И это всё — ведомство Си/С++?
    ... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
    Перекуём баги на фичи!
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.