Я смущен о том, как устанавливается кодировка выходных файлов.Автоматическое назначение кодировки символов?
У меня есть тестовый файл с контентом «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?
Можете ли вы привести пример входного файла, который создает другой выходной файл (включая точные байты в каждом)? На какой платформе вы работаете? –
С контентом * qwe *, UTF-8 и т.д. ISO88591 полностью эквивалентны (* qwe * и «нормальные» разрывы строк находятся в исходном диапазоне ASCII 0-127). Если что-то говорит, что это UTF-8, лучше сказать: «Я не могу сказать, какой из многих возможных». – deviantfan
Да, я подумал, но почему это автоматически меняется на 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 машине и с помощью лязг ++ –