Хорошо, Вот некоторый код, который обрисовывает в общих чертах то, что я пытаюсь сделать.
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <iostream>
#include <sstream>
int main( int c, char *v[] )
{
int fd = open( "data.out", O_RDONLY | O_NONBLOCK );
std::cout << "fd = " << fd << std::endl;
char buffer[ 1024000 ];
ssize_t nread;
std::stringstream ss;
while( true )
{
if ( (nread = read( fd, buffer, sizeof( buffer ) - 1 )) < 0 )
break;
ss.write( buffer, nread );
while( true )
{
std::stringstream s2;
std::cout << "pre-get : " <<
(((ss.rdstate() & std::ios::badbit) == std::ios::badbit) ? "bad" : "") << " " <<
(((ss.rdstate() & std::ios::eofbit) == std::ios::eofbit) ? "eof" : "") << " " <<
(((ss.rdstate() & std::ios::failbit) == std::ios::failbit) ? "fail" : "" ) << " " <<
std::endl;
ss.get( *s2.rdbuf() );
std::cout << "post-get : " <<
(((ss.rdstate() & std::ios::badbit) == std::ios::badbit) ? "bad" : "") << " " <<
(((ss.rdstate() & std::ios::eofbit) == std::ios::eofbit) ? "eof" : "") << " " <<
(((ss.rdstate() & std::ios::failbit) == std::ios::failbit) ? "fail" : "" ) << " " <<
std::endl;
unsigned int linelen = ss.gcount() - 1;
if ( ss.eof() )
{
ss.str( s2.str() );
break;
}
else if ( ss.fail() )
{
ss.str( "" );
break;
}
else
{
std::cout << s2.str() << std::endl;
}
}
}
}
Это во-первых читает большие блоки данных в буфер данных. Я знаю, что существует лучший C++ способы внести свой вклад, но в моем реальном приложении мне вручают символ [] буфер и длину.
Я затем пишу буфер в станд.:: stringstream возражают, таким образом, я могу удалить строку за один раз из него.
Я думал, что буду использовать получение (streambuf и) метод на stringstream для записи одной строки в другой stringstream, где я могу затем произвести его.
Игнорирование того, что это не может быть лучшим способом извлечь строку за один раз из буфера, в котором я читал (хотя я хотел бы, чтобы любой предложил лучшую альтернативу той, я отправляю здесь), как только первое ss.get( *s2.rdbuf() )
назван ss
находится в состоянии сбоя, и я не могу удаться почему. Существует много данных во входном файле так ss
должен определенно содержать больше чем одну строку входа.
Какие-либо идеи?
Я проверил это в Windows, чтобы вы могли захотеть проверить это;
Если данные. Начты начинается с новой строки, я получаю такую же проблему, у вас есть SS .get (* s2.rdbuf ()) работает нормально для первого звонка.
Когда он называется во второй раз, текущее положение потока не продвинулось мимо EOL. Поэтому, когда во второй момент немедленно попытайтесь прочитать EOL, и поскольку никакие другие символы не были скопированы, он устанавливает бит провал.
Быстро и, возможно, грязное исправление:
ss.get( *s2.rdbuf() );
// Get rid of EOL (may need an extra if file contains both \r and \n)
ss.get();
Мне кажется, что первый (и, вероятно, самый большой) шаг, чтобы стать приличным Эффективность состоит в том, чтобы минимизировать копирование данных. Поскольку вам дают данные в CHAR [] с длиной, моя первая тенденция будет начать с создания Strestream
, используя этот буфер. Затем вместо копирования строки за раз на другой Stretream (или StringStream) я копировал строки по одному в то время, который вы будете использовать, чтобы написать их на вывод.
Если вам разрешено изменить содержимое буфера, другая возможность будет разбирать буфер в строки, просто заменяя каждого «\ n» с A '\ 0'. Если вы собираетесь сделать это, вы обычно хотите создать вектор (DECE и т. Д.) УК на начало каждой строки, а также (то есть найдите первое «\ R» или «\ n», а также Замените его «\ 0». Затем следующее, кроме «\ R» или '\ N', является началом следующей строки, поэтому ее адрес в вашем векторе).
Я также усердно подумал, сможете ли вы избежать вывода линии на A-A-Time. Чтение через большой буфер, чтобы найти новую линию относительно медленного. В любом случае, если вы собираетесь в конечном итоге написать одну строку за другим, вы можете избежать всего этого, просто пишете на весь буфер до выходного потока и выполняемой с ним.