2010-10-05 25 views
6

¿Cómo leo una línea FIFO/nombrada línea por línea desde una aplicación C++/Qt Linux?¿Cómo leo una línea FIFO/nombrada línea por línea desde una aplicación C++/Qt Linux?

Hoy puedo abrir y leer desde una fifo desde un programa Qt, pero no consigo que el programa lea los datos línea por línea. Qt lee el archivo completo, lo que significa que espera hasta que el "emisor" cierre su sesión.

Tomemos un ejemplo con algunos comandos de shell para mostrar lo que me gustaría que hiciera la aplicación.

En primer lugar crear un FIFO

mkfifo MyPipe 

entonces podemos usar cat para leer de la FIFO

cat MyPipe 

Y entonces enviamos algunos datos con otro gato

cat > MyPipe 

Y luego comience a escribir algo, y cada vez que presione enter, llegará al lector. Y luego, cuando lo cierras con Ctrl + D, terminan ambos lados.

Ahora el remitente es fácil de crear con QTextStream, , solo necesita enjuagar cuando desea enviar.

QFile file("MyPipe"); 
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) 
    return; 

QTextStream out(&file); 
for(int i=0; i<3; i++) { 
    out << "Hello...: " << i << "\n"; 
    out.flush(); 
    sleep(2); 
} 

file.close(); 

Pero entonces a escribir un pequeño lector que lee línea a línea es donde estoy atascado en este momento, todos mis intentos con el lib Qt termina con eso consigo los datos, pero no hasta que el remitente utiliza file.close() en el fifo. No cuando él descarga, como ocurre cuando uso cat para leer.

como en este ejemplo:

QFile file("MyPipe"); 
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) 
    return 0; 

QTextStream in(&file); 
QString line; 
do { 
    line = in.readLine(); 
    qDebug() << line; 
} while (!in.atEnd()); 


file.close(); 

¿Qué me falta?

Se siente como que necesito utilizar algún tipo de isReady o lineAvailable en la corriente o algo por el estilo, pero no puedo encontrar nada en la documentación que se ajusta ...

/Gracias


Nota:

Si voy con el estilo de bajo nivel C y con un carácter leído en el momento en que hago llegar al mar Im estilo rching para. Pero sería bueno poder hacer el mismo estilo Qt.

FILE *fp; 
fp=fopen("MyPipe", "r"); 
char c; 
while((c=getc(fp)) != EOF) 
{ 
    printf("%c",c); 
} 
fclose(fp); 

actualización:

Cuando comienzo un depurador del programa está colgado en la readLine(), y no continuará hasta que la otra parte se cierra la FIFO.

Y me pongo la misma utilizando ">>"

line = in.readLine(); 
    in >> line; 
+1

¿Podría ser que la tubería se esté leyendo inmediatamente, y en realidad es la salida de la pantalla que se está almacenando? Usaste 'qDebug() << line;' y no veo ninguna descarga. –

+0

Buen punto, no pensé en eso. – Johan

Respuesta

4

Utilice el estilo c de bajo nivel y lea un carácter a la vez.

FILE *fp; 
fp=fopen("MyPipe", "r"); 
char c; 
while((c=getc(fp)) != EOF) 
{ 
    printf("%c",c); 
} 
fclose(fp); 
+0

'c' debe ser' int', de lo contrario podría ser un bucle infinito si 'char' no está firmado (' EOF' es un entero negativo ('-1 'típicamente)). – jfs

2

No sé lo que no funciona, pero se puede intentar depurarlo usando strace:

strace -o writer.log -e trace=write ./writer 
strace -o reader.log -e trace=read ./reader 

La primera line registrará todas las llamadas al sistema de escritura realizadas por su programa de escritura. La segunda línea funciona de manera similar. De esta forma puede rastrear la llamada al sistema y asegurarse de que su descarga funcione.

Si ve una llamada repetida para leer, con la hora y los datos correctos, entonces tiene un problema con QTextStream.

¿Qué sucede si no usas QTextStream, sino que lees directamente del archivo?

+0

strace es bueno, y comencé un "watch tail reader.log" en otra ventana y puedo ver que él obtiene los datos que le envío. – Johan

+0

@Johan: ¿estás seguro de que el problema está en el lado del lector? – shodanex

+0

95% seguro ya que si reemplazo la "versión Qt" con la "versión C", funciona. – Johan

1

Puede intentar abrir el archivo en el lado del lector con la bandera QIODevice::Unbuffered.

+1

idea de Dios, pero sigue siendo la misma :( – Johan

2
if(file.bytesAvailable()) 
QString line = file.readLine(); 

Usted podría utilizar algo como esto.

+0

La implementación de QFile de bytesDisponible NO FUNCIONA para archivos especiales, incluyendo canalizaciones con nombre, ¡y de hecho bloquea la aplicación! –

Cuestiones relacionadas