2015-04-18 3 views
-1

Я смущен о том, как устанавливается кодировка выходных файлов.Автоматическое назначение кодировки символов?

У меня есть тестовый файл с контентом «qwe» (по одному символу в строке). Я проверил несколько кодировок ISO-x. Я прочитал файл и создаю выходной файл. Но выходной файл всегда кодируется в UTF-8. Это само по себе сбивает с толку, так как я никогда явно не писал код для кодирования выходного файла UTF-8. Более запутанным является то, что в другой программе у меня есть вход UTF-8 и получаю как вывод некоторого ISO-кодирования ... снова, без меня, чтобы он делал изменения, которые он кодировал.

Это мой тестовый код:

#include <iostream> 
#include <fstream> 

using namespace std; 

int main(){ 

    string in_file = "in.txt"; // some ISO encoding (e.g.) 
    ifstream in(in_file.c_str()); 
    ofstream out; 
    out.open("out.txt"); 
    while (in.good()) { 
     std::string line; 
     getline(in, line); 
     out << line << endl; 
    } 
    out.close(); // output file is in UTF-8 

} 

Код другой программы, которая производит некоторые ISO с UTF-8 входными очень долго, и я не мог найти, где разница между тестовой программой и моим фактический. Но, возможно, понимание того, почему тестовая программа ведет себя так, как это делает, уже позволяет мне разобраться с проблемой с другой.

Итак, в основном мой вопрос: почему выходной файл установлен в UTF-8 или что определяет кодировку объектов потока.

EDIT:

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

Итак, у меня есть две функции, работающие на уровне поверхности, построившие trie из списка входных данных, которые также содержат код для генерации DOT-кода для graphviz.

/* 
    * 
    * name: make_trie 
    * @param trie Trie to build 
    * @param type Type of tokens to build trie for 
    * @param gen_gv_code Determines wheter to generate graphviz-code 
    * (for debug and maintanance purposes) 
    * @return 
    * 
    */ 
    bool make_trie(Trie* trie, std::string type, bool gen_gv_code=false){ 
     if (gen_gv_code){ 
      gv_file 
      << "digraph {\n\t" 
      << "rankdir=LR;\n\t" 
      << "node [shape = circle];\n\t" 
      << "1 [label=1]\n\t" 
      << "node [shape = point ]; Start\n\t" 
      << "Start -> 1\n\t\t"; 
     } 
     Element* current = wp_list->iterate(); 
     state_symbol_tuple* sst; 
     std::string token = "<UNDEF>"; // token to add to trie 
     // once the last entry in the input list is encountered, make_trie() 
     // needs to run for as many times as that entry has letters +1 - the 
     // number of letters of taht stringa lready encoded into the trie to 
     // fully encode it into it. 
     bool last_token = false; 
     bool incr = false; 
     while (true){ 
      if (type == "tag") { token = current->get_WPTuple_tag(); } 
      else if (type == "word") { token = current->get_WPTuple_word(); } 
      else { 
       cerr 
       << "Error (trainer.h):" 
       << "Unkown type '" 
       << type 
       << "'. Token has not been assigned." 
       << endl; 
       abort(); 
      } 
      // last_state is pointer to state the last transition in the trie 
      // that matched the string led to 
      sst = trie->find_state(token); 
      incr = trie->add(current, sst, gv_file, gen_gv_code); 
      // as soon as the last token has been encoded into the trie, break 
      if (last_token && sst->existing) { break; } 
      // go to the next list item only once the current one is represented 
      // in the trie 
      if (incr) { 
       // Once a word has been coded into the trie, go to the next word. 
       // Only iterate if you are not at the last elememt, otherwise 
       // you start at the front of the list again. 
       if (current->next != 0){ 
        current = wp_list->iterate(); incr = false; 
       } 
      } 
      // enable the condition for the last token, as this is a boundary 
      // case 
      if (current->next == 0) { last_token = true;} 
      // free up memory allocated for current sst 
      delete sst; 
     } 
     if (gen_gv_code){ 
      gv_file << "}"; 
      gv_file.close(); 
     } 
     return true; 
    } 


/* 
* 
* name: Trie::add 
* @details Encodes a given string into the trie. If the string is not 
* in the trie yet, it needs to be passed to this function as many 
* times as it has letters +1. 
* @param current list element 
* @param sst state_symbol_tuple containing information on the last 
* state that represents the string to be encoded up to some point. 
* Also contains the string itself. 
* @return returns boolean, true if token is already represented 
* in trie, false else 
* 
*/ 
bool Trie::add(Element* current, state_symbol_tuple* sst, \ 
    std::ofstream &gv_file_local, bool gen_gv_code){ 
    if (current != 0){ 
     // if the word is represented in the trie, increment its counter 
     // and go to the next word in the list 
     if (sst->existing){ 
      (((sst->state)->find_transition(sst->symbol))->get_successor())->increment_occurance(); 
      if (gen_gv_code){ 
       gv_file_local 
       << (((sst->state)->find_transition(sst->symbol))->get_successor())->get_id() 
       << "[shape = ellipse label = \"" 
       << (((sst->state)->find_transition(sst->symbol))->get_successor())->get_id() 
       << "\nocc: " 
       << (((sst->state)->find_transition(sst->symbol))->get_successor())->get_occurance() 
       //~ << "\naddr: " 
       //~ << ((sst->state)->find_transition(sst->symbol))->get_successor() 
       << "\" peripheries=2]\n\t\t"; 
      } 
      return true; 
     } 
     // if the current string is a substring of one already enoced into 
     // the trie, make the substring an accepted one too 
     else if (sst->is_substring){ 
      (((sst->state)->find_transition(sst->symbol))->get_successor()) \ 
      ->make_accepting(); 
     } 
     // if the word isn't represented in the trie, make a transition 
     // for the first character of the word that wasn't represented 
     // and then look for the word anew, until it *is* represented. 
     else { 
      (sst->state)->append_back(sst->symbol); 
      // as the new transition has been appended at the back 
      // "last" is that new transition 
      // make an empty successor state that the new transition 
      // points to 
      ((sst->state)->get_last())->make_successor(); 
      // increment total state count 
      increment_states_total(); 
      // give the newly added state a unique ID, by making its ID 
      // the current number of states 
      (((sst->state)->get_last())->get_successor())->set_id(get_states_total()); 
      if (gen_gv_code){ 
       gv_file_local << (sst->state)->get_id() << " -> " << get_states_total() 
              << "[label=\""; 
       if (sst->symbol == '"') { 
        gv_file_local << "#"; 
       } 
       else{ 
        gv_file_local << sst->symbol; 
       } 
       gv_file_local << "\"]\n\t\t"; 
      } 
      get_states_total(); 
      // if the length of the input string -1 is equal to the 
      // index of the last symbol, that was processed, then that 
      // was the last symbol of the string and the new state needs 
      // to become an accepting one 
      if (sst->index == (sst->str_len-1)){ 
       // access the newly created successor state 
       // define it as an accepting state 
       (((sst->state)->get_last())->get_successor())->make_accepting(); 
      } 
      else if (gen_gv_code){ 
       gv_file_local 
       << get_states_total() 
       << "[shape = circle label = \"" 
       << (((sst->state)->find_transition(sst->symbol))->get_successor())->get_id() 
       //~ << "\naddr: " 
       //~ << ((sst->state)->find_transition(sst->symbol))->get_successor() 
       << "\"]\n\t\t"; 
      } 
     } 
    } else { cerr << "list to build trie from is empty" << endl; abort();} 
    return false; 
} 

Выходной файл открывается следующим образом:

gv_file.open("gv_file"); 

И передал так:

make_trie(trie_words, "word", true); 

Поскольку это о проблемах с кодировкой, детали пФ реализации дону 'z matter, только бит, где DOT-код записывается в выходной файл.

Мой тест-вход это (в UTF-8):

ascii-range 

ütf-8-ränge 

мой выход это (в ISO-8859)

digraph { 
    rankdir=LR; 
    node [shape = circle]; 
    1 [label=1] 
    node [shape = point ]; Start 
    Start -> 1 
     1 -> 2[label="a"] 
     2[shape = circle label = "2"] 
     2 -> 3[label="s"] 
     3[shape = circle label = "3"] 
     3 -> 4[label="c"] 
     4[shape = circle label = "4"] 
     4 -> 5[label="i"] 
     5[shape = circle label = "5"] 
     5 -> 6[label="i"] 
     6[shape = circle label = "6"] 
     6 -> 7[label="-"] 
     7[shape = circle label = "7"] 
     7 -> 8[label="r"] 
     8[shape = circle label = "8"] 
     8 -> 9[label="a"] 
     9[shape = circle label = "9"] 
     9 -> 10[label="n"] 
     10[shape = circle label = "10"] 
     10 -> 11[label="g"] 
     11[shape = circle label = "11"] 
     11 -> 12[label="e"] 
     12[shape = ellipse label = "12 
occ: 1" peripheries=2] 
     1 -> 13[label="Ã"] 
     13[shape = circle label = "13"] 
     13 -> 14[label="Œ"] 
     14[shape = circle label = "14"] 
     14 -> 15[label="t"] 
     15[shape = circle label = "15"] 
     15 -> 16[label="f"] 
     16[shape = circle label = "16"] 
     16 -> 17[label="-"] 
     17[shape = circle label = "17"] 
     17 -> 18[label="8"] 
     18[shape = circle label = "18"] 
     18 -> 19[label="-"] 
     19[shape = circle label = "19"] 
     19 -> 20[label="r"] 
     20[shape = circle label = "20"] 
     20 -> 21[label="Ã"] 
     21[shape = circle label = "21"] 
     21 -> 22[label="€"] 
     22[shape = circle label = "22"] 
     22 -> 23[label="n"] 
     23[shape = circle label = "23"] 
     23 -> 24[label="g"] 
     24[shape = circle label = "24"] 
     24 -> 25[label="e"] 
     25[shape = ellipse label = "25 
occ: 1" peripheries=2] 
     } 

Так да ... как я мог обеспечить мой вывод также закодирован в utf8?

+0

Можете ли вы привести пример входного файла, который создает другой выходной файл (включая точные байты в каждом)? На какой платформе вы работаете? –

+0

С контентом * qwe *, UTF-8 и т.д. ISO88591 полностью эквивалентны (* qwe * и «нормальные» разрывы строк находятся в исходном диапазоне ASCII 0-127). Если что-то говорит, что это UTF-8, лучше сказать: «Я не могу сказать, какой из многих возможных». – deviantfan

+0

Да, я подумал, но почему это автоматически меняется на UTF8 в этом случае, а в другом - на некоторый ISO, когда вход в UTF8. @Alan Stokes Да , у меня есть, например, этот фрагмент из файла UTF8: '#sentence No. 1 Бундестаг \t ÄN' и я получаю' орграф { \t rankdir = LR; \t узел [форма = круг]; \t 0 [LABEL = 0] \t узел [форма = точка]; Пуск \t Пуск -> 0 \t \t 0 -> 1 [этикетка = "A"] \t \t 1 [форма = круг этикетка = "1"] \t \t 1 -> 2 [этикетка = ""] \t \t 2 [форма = круг этикетка = "2"] \t \t 2 -> 3 [этикетка = "N"] \t \t 3 [форма = эллипс метка = "3 ОКК: 1" периферий = 2] 'в ISO-8859-15 Я нахожусь в Linux машине и с помощью лязг ++ –

ответ

1

В UTF-8 некоторые символы кодируются как более чем один байт. Например, для ä требуется два байта для кодирования. Ваш код для чтения строки полностью игнорирует это и принимает один байт на символ. Затем вы выводите байты отдельно; это не законный UTF-8, поэтому все, что вы используете для разработки набора символов, выводит его на ISO-8859.

В частности, два символа Ã затем , закодированные в ISO-8859 точно так же, как 2 байта, которые кодируют ä в UTF-8.

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

+0

Вы можете сделать хуже, чем начать с чтения http://www.joelonsoftware.com/articles/Unicode.html. –

+0

Я понимаю сейчас, спасибо! Я также определил фрагмент, который вызывает это. Его, где я пытаюсь сделать вектор char из строки, и поскольку в строке есть символы, которые занимают больше байта, чем 1, они разбиваются на 2 символа в векторе char (просто переписывая то, что вы сказали, чтобы показать, что я понимать это). Итак, что я хотел сделать, это не работает. Мне нужно как-то перебрать строку и сделать ее как-то 0 завершенной, чтобы распознать конец строки. –