2015-05-12 15 views
5

Stavo testando come leggere i dati da un std::streamstring ma mi sto sbagliando, qualcuno potrebbe indicare qual è il problema? e dare un modo corretto per leggerlo?Lettura di contenuti da uno strings

Il mio codice di prova è:

#include <iostream> 
#include <string> 
#include <sstream> 

#define BUFFER_SIZE 16 

int main(int argc, char ** argv) 
{ 

    std::stringstream ss; 
    ss << "Un texto con datos de ejemplo para probar la extacción de un stream"; 

    std::cout << "Stream contents: '" << ss.str() << "'" << std::endl; 

    char buffer[BUFFER_SIZE] = {0}; 

    std::streamsize read = 0; 

    do { 
     read = ss.readsome(buffer, BUFFER_SIZE - 1); 
     std::cout << "Read: " << ss.gcount() << std::endl; 
     std::cout << buffer << std::endl; 
     std::cout << "---" << std::endl; 
     std::fill(buffer, buffer + BUFFER_SIZE, 0); 
    } while (read > 0); 

    return 0; 
} 

e sto ottenendo l'output:

Stream contents: 'Un texto con datos de ejemplo para probar la extacci¾n de un stream' 
Read: 15 
Un texto con da 
--- 
Read: 15 
tos de ejemplo 
--- 
Read: 15 
para probar la 
--- 
Read: 15 
extacci¾n de un 
--- 
Read: 5 
stre 
--- 
Read: 0 

--- 

Come si può notare l'ultima operazione di lettura legge solo 5 caratteri lasciando fuori gli ultimi due 'am 'anche se avrebbe dovuto essere in grado di leggerlo. Mi manca qualcosa?

+0

Penso che sia necessario lavorare con la versione 'wchar_t' di stream e stringhe. – Nawaz

+1

Sostituire il 'ó' con un normale risultato' o' nello stesso risultato. Perché dovrei lavorare comunque con 'wchar_t'? –

+1

Ho copiato il tuo codice in un file .cpp e compilato usando g ++ senza argomenti. Sulla mia macchina, l'intero stream viene stampato senza troncamento, ma il primo read acquisisce solo un carattere. Sto usando gcc 4.9.2 e glibc 2.21-3. –

risposta

3

In realtà, readsome legge solo l'available characters e ciò che dipende dalla piattaforma, quindi è bene consentire di restituire 0 mentre ci sono ancora caratteri nello stream e una chiamata successiva potrebbe probabilmente restituire i caratteri mancanti. Per ottenere tutti i dati disponibili, preferisco usare read in combinazione con gcount per ottenere il numero di caratteri che si leggono.

do { 
    ss.read(buffer, BUFFER_SIZE - 1); 
    read=ss.gcount(); 
    std::cout << "Read: " << ss.gcount() << std::endl; 
    std::cout << buffer << std::endl; 
    std::cout << "---" << std::endl; 
    std::fill(buffer, buffer + BUFFER_SIZE, 0); 
} while (read > 0); 

Solo per chiarezza:
Mentre io credo, il behavoir hai osservato è consentita dallo standard, non vedo il motivo per cui l'attuazione dovrebbe comportarsi come questo, quando il flusso di input si basa su una stringa letterale (Non ho familiarità con i dettagli di implementazione dei flussi). Quello che è possibile verificare è che se read corrisponde effettivamente a rdbuf()->in_avail() e se non lo fa, potrebbe trattarsi di un bug del compilatore.

+0

Fare in modo che il cambiamento risolva il problema. Quindi 'readsome' dovrebbe essere usato in un modo di raggruppamento? (dal momento che potrebbe restituire l'evento 0 anche se il contenuto è rimasto). –

+0

@ Javier Mr: Non lo so davvero. Per quello che posso dire, l'idea che sta dietro a readsome è quella di darti tutti i personaggi che sono disponibili senza una systemcall potenzialmente bloccante. Quindi non sono sicuro che otterrai tutti i dati. D'altra parte non capisco, perché l'implementazione specifica di VC++ 2008 non ti darà tutti i dati da un oggetto stringa locale. Se si sta parlando di threadpool, tuttavia, direi di no poiché non è protetto da thread, quindi è necessario serializzarlo comunque. – MikeMB

+0

sì Intendevo le chiamate consecutive a thread singolo. Capisco lo scopo di 'readsome' di bloccare il meno possibile. Comunque ho provato a cambiare la condizione di do-while a '! Ss.eof()' e apparentemente 'readsome 'non legge mai l'intero stream, anche controllato' in_avail' e inizia con un valore di 50 e in ogni chiamata diminuisce senza mai leggere gli ultimi. Grazie. –