Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.87/23: Рейтинг темы: голосов - 23, средняя оценка - 4.87
4 / 4 / 2
Регистрация: 19.08.2013
Сообщений: 26
1

Чтение Unicode

15.09.2013, 16:25. Просмотров 4233. Ответов 24
Метки нет (Все метки)

Есть файл в кодировке Unicode. Надо вывести его содержимое в другой файл и в консоль. Использую двухбайтовый тип wchar, но вместо текста выводятся закорючки, причём в выходном файле и консоли они разные.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <windows.h>
#include <fstream>
using namespace std;
 
int main()
{
    setlocale(0,"");
    wchar_t c;
    wifstream Text("formula.txt");
    if(!Text.is_open()){
        cout<<"Error";
        return 0;
    }
    wofstream Output("formula2.txt");
    if(!Output.is_open()){
        cout<<"Error";
        return 0;
    }
    while(Text>>c){
        wcout<<c;
        Output<<c;
    }
    Text.close();
    Output.close();
    system("PAUSE");
    return 0;
}
Добавлено через 22 часа 34 минуты
Никто с этим не сталкивался?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.09.2013, 16:25
Ответы с готовыми решениями:

Чтение из файла unicode-символов
Добрый день. помогите пожалуйста с таким вопросом. Имеется файл, сохранённый с кодировкой unicode....

Чтение файла в Unicode формате
Как можно за одно обращение к потоку забрать не один байт, а сразу два? Необходимо считать все...

Чтение из файла в формате Unicode
Прошу помощи, пытаюсь считать информацию из файла который в кодировке Unicode в ANSI все...

Чтение UNICODE символов из STDOUT процесса
У меня есть процесс (cmd.exe) создан через WINAPI функцию CreateProcess. К процессу подключено 2...

24
5477 / 4872 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
15.09.2013, 16:35 2
Цитата Сообщение от Wollen Посмотреть сообщение
Никто с этим не сталкивался?
Ещё как сталкивались... Как вариант (из файла на консоль):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <fstream>
#include <Windows.h>
using namespace std;
 
int main()
{
    setlocale(0, ".1251"); //включили кодировку.
    //SetConsoleCP (1251); 
    //SetConsoleOutputCP (1251); // или так.
    
    char buff[500];
    wchar_t wbuff[500];
 
    ifstream f("upload.txt");
    
    f.getline(buff, 500); // в буффер char из файла UTF-8.
    
    MultiByteToWideChar(CP_UTF8, 0, buff, 500, wbuff, 500); //из буфера char в буфер wchar_t .
    setlocale(0, "rus_rus.866"); // //включаем другую кодировку.
    wcout << wbuff << endl; // выводим содержимое буфера wchar_t
    
    setlocale(0, ".1251"); // вернули кодировку.
    
    system("pause");
    return 0;
}
1
4 / 4 / 2
Регистрация: 19.08.2013
Сообщений: 26
15.09.2013, 17:40  [ТС] 3
Цитата Сообщение от alsav22 Посмотреть сообщение
Ещё как сталкивались... Как вариант (из файла на консоль):
Не работает к сожалению.
Ввожу в файл "(((F)˅(G))→(H))". В буфер buff считывается [-17, -69, -65, 40, 40, 40, 70, 41, -53, -123, 40, 71, 41, 41, -30, -122, -110, 40, 72, 41, 41]. В wbuff [65279, 40, 40, 40, 70, 41, 709, 40, 71, 41, 41, 8594, 40, 72, 41, 41].
Но wcout << wbuff; или wcout<<wbuff[i]; не выводят ничего
0
5477 / 4872 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
15.09.2013, 17:57 4
Цитата Сообщение от Wollen Посмотреть сообщение
Ввожу в файл
Про ввод в файл ничего не знаю. В коде, который я предложил, никакого ввода нет. Как у вас ввод сделан, нужно отдельно разбираться.
Цитата Сообщение от Wollen Посмотреть сообщение
Не работает к сожалению.
У вас не работает... Файл давайте, проверю как у меня будет.
0
4 / 4 / 2
Регистрация: 19.08.2013
Сообщений: 26
15.09.2013, 18:27  [ТС] 5
Цитата Сообщение от alsav22 Посмотреть сообщение
Про ввод в файл ничего не знаю. В коде, который я предложил, никакого ввода нет. Как у вас ввод сделан, нужно отдельно разбираться.

У вас не работает... Файл давайте, проверю как у меня будет.
Я неправильно выразился. С клавиатуры в файл ничего не ввожу. Нужно достать данные из файла(включая символы, которых нет в стандартной кодировке) и дальше работать с ним, как с обычным массивом символов для построения синтаксического анализатора.
0
Вложения
Тип файла: txt formula.txt (38 байт, 22 просмотров)
5477 / 4872 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
15.09.2013, 19:28 6
Как этот файл делался?

Добавлено через 25 минут
Там в начале BOM записан, который нужно пропустить.
0
4 / 4 / 2
Регистрация: 19.08.2013
Сообщений: 26
15.09.2013, 19:29  [ТС] 7
Цитата Сообщение от alsav22 Посмотреть сообщение
Как этот файл делался?
Копированием символов из ворда )
0
5477 / 4872 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
15.09.2013, 19:31 8
Цитата Сообщение от Wollen Посмотреть сообщение
Копированием символов из ворда )
Копированием во что? В файл блокнота?
0
4 / 4 / 2
Регистрация: 19.08.2013
Сообщений: 26
15.09.2013, 19:32  [ТС] 9
Цитата Сообщение от alsav22 Посмотреть сообщение
Копированием во что? В файл блокнота?
так точно
0
5477 / 4872 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
15.09.2013, 19:33 10
Кроме блокнота, есть ещё у вас редакторы, которые могут файлы в юникоде создавать?
0
2572 / 2188 / 233
Регистрация: 03.07.2012
Сообщений: 7,901
Записей в блоге: 1
15.09.2013, 19:33 11
В файле есть символы, которых нет в 866-й кодировке, поэтому вывод прерывается, как только встречается такой символ. Вот измененный кусок кода от alsav22, где несуществующие символы заменяются на "@":
C++
1
2
3
4
5
6
7
8
9
    f.getline(buff, 500); // в буфер char из файла UTF-8.
    
    MultiByteToWideChar(CP_UTF8, 0, buff+3, 500, wbuff, 500);       // из буфера char в буфер wchar_t...
 
    WideCharToMultiByte(866,0,wbuff,-1,(LPSTR)buff,500,"@",NULL);   // ... и обратно, заменяем отсутствующие в кодовой странице символы на @  
//    setlocale(0, ".1251"); //включили кодировку 1251
    
    cout << buff << endl; // выводим содержимое буфера   
    system("pause");
2
5477 / 4872 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
15.09.2013, 19:56 12
Вот код, с дополнениями zer0mail, который более или менее работает. Если BOM есть, то пропускает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <fstream>
#include <Windows.h>
using namespace std;
 
int main()
{
    //setlocale(0, ".1251"); //включили кодировку.
    //SetConsoleCP (1251); 
    //SetConsoleOutputCP (1251); // или так.
    
    char buff[500];
    wchar_t wbuff[500];
    
    ifstream f("formula.txt", ios::binary);
    if (!f) cout << "Error!" << endl;
    else
    {
        f.get(buff, 4); // считали первые три байта
        
        if ((unsigned char)buff[0] == 0xEF && (unsigned char)buff[1] == 0xBB && (unsigned char)buff[2] == 0xBF); // если BOM есть, то читаем в буфер c позции за BOM
        else  f.seekg(0); // если BOM нет, то курсор в начало файла
        
        int i = 0;
        while (f.get(buff[i])) ++i;
        buff[i] = '\0';
        f.close();
        
        MultiByteToWideChar(CP_UTF8, 0, buff, 500, wbuff, 500); //из буфера char в буфер wchar_t .
        WideCharToMultiByte(866, 0, wbuff, -1, (LPSTR)buff, 500, "@", NULL);
        //setlocale(0, "rus_rus.866"); //включаем другую кодировку.
        //wcout << wbuff << endl; // выводим содержимое буфера wchar_t
        cout << buff << endl;
        //setlocale(0, ".1251"); // вернули кодировку.
    }
    
    cout << endl;
    system("pause");
    return 0;
}
1
Миниатюры
Чтение Unicode  
4 / 4 / 2
Регистрация: 19.08.2013
Сообщений: 26
15.09.2013, 20:13  [ТС] 13
Цитата Сообщение от alsav22 Посмотреть сообщение
Вот код, с дополнениями zer0mail, который более или менее работает. Если BOM есть, то пропускает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <fstream>
#include <Windows.h>
using namespace std;
 
int main()
{
    //setlocale(0, ".1251"); //включили кодировку.
    //SetConsoleCP (1251); 
    //SetConsoleOutputCP (1251); // или так.
    
    char buff[500];
    wchar_t wbuff[500];
    
    ifstream f("formula.txt", ios::binary);
    if (!f) cout << "Error!" << endl;
    else
    {
        f.get(buff, 4); // считали первые три байта
        
        if ((unsigned char)buff[0] == 0xEF && (unsigned char)buff[1] == 0xBB && (unsigned char)buff[2] == 0xBF); // если BOM есть, то читаем в буфер c позции за BOM
        else  f.seekg(0); // если BOM нет, то курсор в начало файла
        
        int i = 0;
        while (f.get(buff[i])) ++i;
        buff[i] = '\0';
        f.close();
        
        MultiByteToWideChar(CP_UTF8, 0, buff, 500, wbuff, 500); //из буфера char в буфер wchar_t .
        WideCharToMultiByte(866, 0, wbuff, -1, (LPSTR)buff, 500, "@", NULL);
        //setlocale(0, "rus_rus.866"); //включаем другую кодировку.
        //wcout << wbuff << endl; // выводим содержимое буфера wchar_t
        cout << buff << endl;
        //setlocale(0, ".1251"); // вернули кодировку.
    }
    
    cout << endl;
    system("pause");
    return 0;
}
Годный костыль, хотя и не выводит юникодину.
0
2572 / 2188 / 233
Регистрация: 03.07.2012
Сообщений: 7,901
Записей в блоге: 1
15.09.2013, 22:20 14
Wollen, если найдешь способ, как вывести английские, русские и математические символы в консоль, напиши. Многие искали, но никто не нашел (имхо)
1
129 / 1 / 1
Регистрация: 16.12.2019
Сообщений: 33
24.02.2020, 20:37 15
Ребята, черт знает как в 13 году было, НО! Если вам консоль, то есть функции (я вам кусочек своего кода кидаю, ибо мне для проверки костыля понадобилась консоль и тип wchar_t, если я правильно понимаю кое-что, в общем для файла они также называются, но я их не тестил, просто только что видел, но для консоли с типом wchar_t все батрачит)
C++
1
2
3
4
  wchar_t c;
    c = getchar();
    std::cout << "c: ";
    putwchar(c); std::cout << "\n";
0
2719 / 1669 / 347
Регистрация: 09.09.2017
Сообщений: 6,931
25.02.2020, 10:49 16
Код
$ g++ main.c
$ ./a.out 
ЫЫ
c: �
Это иллюстрация что ваш вариант не работает. Как минимум, при вводе надо getchar заменить на getwchar.
Во-вторых, стандартная виндовая консоль ужасно кривая и старается не отображать юникод когда только может. Но ее можно заставить:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
 
#ifdef WIN32
  #include <windows.h>
  #include "fcntl.h"
  __attribute__((constructor)) void coninit(){
    SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
    _setmode(_fileno(stdout), _O_U8TEXT);
    _setmode(_fileno(stdin), _O_U8TEXT);
  }
#endif
 
int main(){
  setlocale(LC_ALL, "");
  wprintf(L"x\u00B2+7x+4\n");
  return 0;
}
Код
$ gcc main.c
$ ./a.out 
x²+7x+4
Это в нормальной консоли, но и в виндовой проверял. Кстати, кучи юникодных символов там нет, например '\uE000'
Да, напомню очевидное: файл исходного кода должен быть в UTF-8. Впрочем, в крайнем случае можно и в ASCII, но тогда юникодные символы придется задавать кодами, как в моем коде '\u00B2'. Читаемость, конечно, снизится.
0
129 / 1 / 1
Регистрация: 16.12.2019
Сообщений: 33
25.02.2020, 11:04 17
Он у меня на вижаке 2019 windows 10 спокойно работает, однако, символов многих и правда нет. Например признак конца строки '\0', можно подробнее о том, каким образом вы сам сиивол Unicode заменили кодом? Я так понимаю \uкод из ASCII шестнадцатиричный?
0
2719 / 1669 / 347
Регистрация: 09.09.2017
Сообщений: 6,931
25.02.2020, 12:37 18
Не понял вопроса. Мой код вы видите, представление символа '²' в виде кода тоже. Для русских букв можно брать коды '\u0410' - '\u042F' (заглавные) и '\u0430' - '\u044f' (строчные).
Цитата Сообщение от Wizard_with_Axe Посмотреть сообщение
Он у меня на вижаке 2019 windows 10 спокойно работает
Код из 15 поста не работает с Юникодом. В лучшем случае - с какой-то устаревшей однобайтной кодировкой вроде cp1251. Это легко проверить если вывести значение символа как число: printf("%u\n", (unsigned int)ch);. Проверьте это на своем коде и на моем. Логика подсказывает результат 219 для вашего варианта и 1067 (оно же 0x042B) для моего.
1
Модератор
Эксперт CЭксперт С++
4004 / 3513 / 622
Регистрация: 07.10.2015
Сообщений: 7,260
25.02.2020, 13:08 19
COKPOWEHEU, почему-то у меня в MS2017, Win7 не воспринимается __attribute__((constructor))
Если записать
C++
1
2
3
4
5
void coninit() {
    SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
    _setmode(_fileno(stdout), _O_U8TEXT);
    _setmode(_fileno(stdin), _O_U8TEXT);
}
и явно вызвать
C++
1
2
3
4
5
6
int main() {
    setlocale(LC_ALL, "");
    coninit();
    wprintf(L"x\u00B2+7x+4\n");
    return 0;
}
то работает. Не подскажете, почему?
0
2719 / 1669 / 347
Регистрация: 09.09.2017
Сообщений: 6,931
25.02.2020, 13:32 20
Цитата Сообщение от liv Посмотреть сообщение
COKPOWEHEU, почему-то у меня в MS2017, Win7 не воспринимается __attribute__((constructor))
Возможно, это gcc-специфичная штука.
Для себя постепенно пишу слой кроссплатформенности, и как раз сегодня добавлял эту функцию вот в таком виде:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
 *  Linux
 */
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
  #ifndef linux
    #define linux 1 //чтобы была всего одна константа, а не десяток
  #endif
  //Linux
  #include <dlfcn.h>
  #include <unistd.h>
  
  #define DynLoad(s) dlopen(s, RTLD_LAZY)
  #define DynFunc(lib, name)  dlsym(lib,name)
  #define DynClose(lib) dlclose(lib)
  #define DynSuffix ".so"
  #define msleep(time_ms) usleep((time_ms)*1000)
  
  #define my_setlocale(category, locale) setlocale(category, locale)
/*
 *  Win 32
 */
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
  #ifndef WIN32
    #define WIN32 1
  #endif
  //Win32
  #define _CRT_SECURE_NO_WARNINGS
  #define _USE_MATH_DEFINES
  #include <windows.h>
  
  #define DynLoad(s) LoadLibrary(s)
  #define DynFunc(lib, name)   GetProcAddress((HINSTANCE)lib, name)
  #define DynClose(lib) FreeLibrary(lib)
  #define DynSuffix ".dll"
  #define msleep(time_ms) Sleep(time_ms)
  
  #include "fcntl.h"
  
  #define my_setlocale(category, locale) (\
    SetConsoleCP(CP_UTF8), SetConsoleOutputCP(CP_UTF8),\
    _setmode(_fileno(stdout), _O_U8TEXT),\
    _setmode(_fileno(stdin), _O_U8TEXT),\
    setlocale(category, locale) )
  
 /*
  *  Other systems (unsupported)
  */
#else
  #error "Unsupported platform"
#endif
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.02.2020, 13:32

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

CStdioFile не поддерживает чтение файлов в формате Unicode. Что делать?
К сожалению CStdioFile не поддерживает чтение текстовых файлов в формате Unicode. Может быть...

C++ и Unicode
Всем привет. Читая про кодовые точки в Java, мне стало интересно как с этим дела в C++. Т.е. для...

Unicode в c++
Нужно вывести в консоли символ: \ Просто так сделать это нельзя, решил использовать Unicode. Код...

Открыть текстовый файл в необходимом режиме (на чтение, на чтение и запись, на добавление)
Открыть текстовый файл в необходимом режиме (на чтение, на чтение и запись, на добавление). (В...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.