Здравствуйте, Adriano, Вы писали:
A>Почему в случае с char файл считывается полностью, а в случае с unsigned char где-то после 7гб чтение прекращается, т.к. выставляется флаг eof? A>размер файла ~12гб
Компилите ведь MSVC?
ИМХО, тут имеет место ошибка в реализации STL.
Файл iosfwd, STL от MSVC 7.1:
// TEMPLATE STRUCT char_traits (FROM <string>)template<class _Elem>
struct char_traits
{ // properties of a string or stream elementtypedef _Elem char_type;
typedef _Elem int_type;
.............
static int_type __cdecl eof()
{ // return end-of-file metacharacterreturn ((int_type)EOF); // при _Elem == unsigned char, здесь будет '\xFF'!
}
Выделенное выше, как я понимаю, неверно, так как (21.1.2 traits typedefs):
typedef INT_T int_type;
Requires: For a certain character container type char_type, a related container type INT_T shall be a type or class which can represent all of the valid characters converted from the corresponding char_type values, as well as an end-of-file value, eof()
Соответственно, на первом же байте с кодом FF чтение затыкается по "концу файла".
Почему работает для char? Потому что для char там специализация (как и требуется стандартом), в которой int_type это int.
As a side note:
A> in.read(&buffer[0],static_cast<streamsize>( buffer.size() & 0xFFFFFFFF ) ); //правильно я делаю преобразование?
Преобразование преобразованием, но с точки зрения стандарта тут UB, потому что внутреннее представление строки не обязано быть массивом символов. Т.е. нужно понимать, что, теоретически, эта конструкция может не пережить переезда на очередную платформу/версию компилятора.
basic_ifstream<unsigned char> не читает файл до конца
Почему в случае с char файл считывается полностью, а в случае с unsigned char где-то после 7гб чтение прекращается, т.к. выставляется флаг eof?
размер файла ~12гб
Re: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, Adriano, Вы писали:
A>просто читаю файл: A>
A>template<class ValueT>
A>void simple_reading(const char* fileName)
A>{
A> basic_ifstream<ValueT> in;
A> in.open(fileName,ios::binary);
A> if ( !in ){
A> return;
A> }
A> basic_string<ValueT> buffer;
A> buffer.resize(1024*1024*100);
A> {
A> size_t offset = 0;
A> while( !in.eof() ){
A> in.read(&buffer[0],static_cast<streamsize>( buffer.size() & 0xFFFFFFFF ) ); //правильно я делаю преобразование?
A> offset += in.gcount();
A> cout << "\roffset = " << offset;
A> }
A> cout << endl;
A> }
A> return;
A>}
A>int _tmain(int argc, _TCHAR* argv[])
A>{
A> if ( argc < 2 ){
A> return 1;
A> }
A> simple_reading<char>(argv[1]);
A> simple_reading<unsigned char>(argv[1]);
A> return 0;
A>}
A>
A>Почему в случае с char файл считывается полностью, а в случае с unsigned char где-то после 7гб чтение прекращается, т.к. выставляется флаг eof? A>размер файла ~12гб
по моему по умолчанию char считается unsigned
поэтому вроде не должно быть разницы
Re[2]: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, quodum, Вы писали:
Q>Здравствуйте, Adriano, Вы писали:
A>>Почему в случае с char файл считывается полностью, а в случае с unsigned char где-то после 7гб чтение прекращается, т.к. выставляется флаг eof? A>>размер файла ~12гб
Q>Компилите ведь MSVC?
Q>ИМХО, тут имеет место ошибка в реализации STL.
Q>Файл iosfwd, STL от MSVC 7.1: Q>
Q> // TEMPLATE STRUCT char_traits (FROM <string>)
Q>template<class _Elem>
Q> struct char_traits
Q> { // properties of a string or stream element
Q> typedef _Elem char_type;
Q> typedef _Elem int_type;
Q> .............
Q> static int_type __cdecl eof()
Q> { // return end-of-file metacharacter
Q> return ((int_type)EOF); // при _Elem == unsigned char, здесь будет '\xFF'!
Q> }
Q>
Q>Выделенное выше, как я понимаю, неверно, так как (21.1.2 traits typedefs): Q>
Q>typedef INT_T int_type;
Q>Requires: For a certain character container type char_type, a related container type INT_T shall be a type or class which can represent all of the valid characters converted from the corresponding char_type values, as well as an end-of-file value, eof()
Q>Соответственно, на первом же байте с кодом FF чтение затыкается по "концу файла".
Q>Почему работает для char? Потому что для char там специализация (как и требуется стандартом), в которой int_type это int.
Как с этим бороться? писать свой traits?
Q>As a side note:
Q>
Q>Преобразование преобразованием, но с точки зрения стандарта тут UB, потому что внутреннее представление строки не обязано быть массивом символов. Т.е. нужно понимать, что, теоретически, эта конструкция может не пережить переезда на очередную платформу/версию компилятора.
vector представляется как массив, это входит в стандарт?
Re[2]: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, Adriano, Вы писали:
A>Как с этим бороться? писать свой traits?
Наверно да. То есть, добавлять свою специализацию для unsigned char в пространство имен std, хотя это вроде бы не вполне корректно, так как это разрешается делать только для пользовательских типов (если я ничего не путаю), коим unsigned char не является.
Однако, действительно ли это нужно? Откуда вообще взялась необходимость работать с потоками из unsigned char?
A>vector представляется как массив, это входит в стандарт?
Касательно вектора -- входит. Именно вектор рекомендуют использовать в качестве "переходника" при работе с внешними API, требующими плоских строковых буферов.
Re[3]: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, Adriano, Вы писали:
A>как сделать специализацию для unsigned char? я новичек в этом деле
Примерно так:
#include <iosfwd> // или где ваша STL определяет char_traitsnamespace std
{
// а сюда копируете специализацию char_traits<char> из stl,
// меняете на char_traits<unsigned char>
// и правите внутренности по смыслу
}
Но, действительно ли это необходимо? Я бы постарался обойтись без потоков на unsigned char (тем более, что до сих пор не могу представить, зачем они понадобились )
Re[4]: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, quodum, Вы писали:
Q>Здравствуйте, Adriano, Вы писали:
A>>Как с этим бороться? писать свой traits?
Q>Наверно да. То есть, добавлять свою специализацию для unsigned char в пространство имен std, хотя это вроде бы не вполне корректно, так как это разрешается делать только для пользовательских типов (если я ничего не путаю), коим unsigned char не является.
Q>Однако, действительно ли это нужно? Откуда вообще взялась необходимость работать с потоками из unsigned char?
мне нужно только читать и писать блоки(без форматирования) + кроссплатформенность. Похоже что проще составить свою оболочку с методами read write.
Если я буду использовать fread, fwrite при чтении блока размером 100мб, данные считаются прямиком в мой буффер или сначала во внутренний буффер FILE, а потом в мой?
Re[5]: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, Adriano, Вы писали:
A>мне нужно только читать и писать блоки(без форматирования) + кроссплатформенность. Похоже что проще составить свою оболочку с методами read write.
Но что мешает использовать обычный std::ifstream?
A>Если я буду использовать fread, fwrite при чтении блока размером 100мб, данные считаются прямиком в мой буффер или сначала во внутренний буффер FILE, а потом в мой?
Это надо смотреть в конкретной реализации стандартной библиотеки. Исходники обычно доступны.
Но я бы сделал для начала как проще. А уже потом, если результаты замера производительности окажутся неудовлетворительными, смотрел на реализацию функции чтения. Скорее всего, лишнее копирование памяти (если оно и есть) потеряется на фоне чтения с диска.
Re[4]: basic_ifstream<unsigned char> не читает файл до конца
Здравствуйте, quodum, Вы писали:
Q>Здравствуйте, Adriano, Вы писали:
A>>как сделать специализацию для unsigned char? я новичек в этом деле
Q>Примерно так:
Q>
Q>#include <iosfwd> // или где ваша STL определяет char_traits
Q>namespace std
Q>{
Q> // а сюда копируете специализацию char_traits<char> из stl,
Q> // меняете на char_traits<unsigned char>
Q> // и правите внутренности по смыслу
Q>}
Q>
Q>Но, действительно ли это необходимо? Я бы постарался обойтись без потоков на unsigned char (тем более, что до сих пор не могу представить, зачем они понадобились )
все началось с string.
Сравниваю две строки(string, т.е. basic_string<char>). Заглянув в исходники basic_string — выяснил, что сравнение выполняется с помощью функции memcmp(название точно не помню, но это не важно), важно что она сравнивает как unsigned char т.е. без знака 'f' < 'ю', что уже не совсем правильно, ведь я работаю с char. Когда я формирую интервал boost::iterator_range<string::iterator> и выполняю сравнение двух интервалов, то сравнение выполняется при помощи lexicographical_compare и получаю 'ю' < 'f'. В итоге критерий сравнения меняется откуда вытекают разные сюрпризы при сортировке. Я оформил код в виде шаблонов и работаю c unsigned char, а это повлекло переход к basic_ifstream<CharT>...