Köra shellkommando från cocoa-app och fånga output

Tråden skapades och har fått 2 svar. Det senaste inlägget skrevs .
1

Hej!

Jag har länge gått och funderat på en app som jag behöver och som jag är sugen på att bygga som ett "lär dig Objective-C projekt". Jag har programmerat sedan barnsben och har, enligt mig själv, rätt bra koll på flertalet programmeringsspråk. Däremot är det såklart alltid lite knöligt att sätta sig in i ett nytt språk och nya API:n som man inte jobbat med förut.

Det jag behöver göra är att köra ett shellkommando och fånga output från det, som sedan parse:as och visas i appen. Kommandot kommer att skriva ut data kontinuerligt, och jag vill alltså fånga upp denna stream och läsa av den med jämna intervaller.

Jag har googlat runt lite, och från vad jag kan klura ut själv verkar det vara en vettig idé att skapa en NSPipe som hookar på sin NSTask med något i stil med [mytask setStandardOutput:mypipe], och sedan plockar ut "availableData" från pipen i jämna intervaller. Frågan är, är det det bästa sättet? Kommandot kommer att generera en sida text i jämna intervaller (t ex var 5:e sekund), och det känns som att man helst vill vänta på en uppdatering, läsa all data och sedan göra en parse. Ifall man bara kör läsningen på en timer kan det hända att man försöker läsa mitt under en uppdatering och då inte får ut all data. Kan man på något sätt styra detta bättre? Jag kan själv ställa output från det som körs, så man kan t ex avsluta varje sida med en viss teckenkombination el dyl. Då kanske det går att läsa kontinuerligt och söka i output efter den strängen, och i sådana fall trigga en parse då?

Dessutom, hur fungerar pipen i objective c, kan man ha en pipe som kontinuerligt läser från output och frigör använt minne allt eftersom? Eller kommer pipen att ta upp mer och mer minne ju lägre NSTask:en körs? Finns det kanske något bättre sätt att åstadkomma detta på än att skapa en NSTask?

Jag är inte speciellt hemma hantering av filer, pipes o dyl, så jag gissar mest här.. Men innan jag bygger en "ostabil" lösning tänkte jag att det kanske är bäst att göra med lite mer invanda programmerare vad som är den bästa approachen Alla förslag och tips uppskattas.

Ursprungligen av Kermit:

Jag har googlat runt lite, och från vad jag kan klura ut själv verkar det vara en vettig idé att skapa en NSPipe som hookar på sin NSTask med något i stil med [mytask setStandardOutput:mypipe], och sedan plockar ut "availableData" från pipen i jämna intervaller. Frågan är, är det det bästa sättet? Kommandot kommer att generera en sida text i jämna intervaller (t ex var 5:e sekund), och det känns som att man helst vill vänta på en uppdatering, läsa all data och sedan göra en parse. Ifall man bara kör läsningen på en timer kan det hända att man försöker läsa mitt under en uppdatering och då inte får ut all data. Kan man på något sätt styra detta bättre? Jag kan själv ställa output från det som körs, så man kan t ex avsluta varje sida med en viss teckenkombination el dyl. Då kanske det går att läsa kontinuerligt och söka i output efter den strängen, och i sådana fall trigga en parse då?

Spara allt som du läser i en buffert. När du stöter på ett separatortecken så tolkar du det som hade lästs fram till dess. När jag har gjort sånt har jag temporärt sparat allt i en NSMutableData och därefter flyttat allt efterföljande till början med memmove(). Det går att göra med realloc() också. Helst bygger du dock parsern så att du kan skicka data till den allteftersom.

Ursprungligen av Kermit:

Dessutom, hur fungerar pipen i objective c, kan man ha en pipe som kontinuerligt läser från output och frigör använt minne allt eftersom? Eller kommer pipen att ta upp mer och mer minne ju lägre NSTask:en körs? Finns det kanske något bättre sätt att åstadkomma detta på än att skapa en NSTask?

En pipe läser inget utan fungerar som en kommunikationskanal som bland annat kan användas mellan olika processer. Det är som en fil där den data som man skriver till den i ena änden kan läsas från den andra, så du behöver inte bekymra dig om att frigöra minne. Det är ett väldigt vanligt sätt att starta andra processer och kommunicera med dem.

Ursprungligen av Marcus K:

Spara allt som du läser i en buffert. När du stöter på ett separatortecken så tolkar du det som hade lästs fram till dess. När jag har gjort sånt har jag temporärt sparat allt i en NSMutableData och därefter flyttat allt efterföljande till början med memmove(). Det går att göra med realloc() också. Helst bygger du dock parsern så att du kan skicka data till den allteftersom.

Menar du att jag bör läsa "availableData" (tror jag den hette) som returnerar all tillgänglig data, och anropa det i jämna intervaller (t ex en gång per sekund) och spara datan jag får ut till en buffer, och sedan vänta på ett "separator"-tecken då jag kör en parse och kopierar allt efter separatorn till början på buffern igen? Och sedan rince-and-repeat på det.

Parsern borde klara av att ta emot "strömmande" data, men jag behöver iaf tolka en rad i taget, dvs att jag separerar input i lästa rader. Smidigast vore kanske någon form av "read until newline"-funktion som skickar ett event med den data som lästs in kanske, och parsern får fånga upp det.. Får klura lite på det där.

Ursprungligen av Marcus K:

En pipe läser inget utan fungerar som en kommunikationskanal som bland annat kan användas mellan olika processer. Det är som en fil där den data som man skriver till den i ena änden kan läsas från den andra, så du behöver inte bekymra dig om att frigöra minne. Det är ett väldigt vanligt sätt att starta andra processer och kommunicera med dem.

Jo, att läsa var väl fel uttryck kanske Mer som en buffer kanske. I alla fall, om jag förstår dig rätt så är bytes som lästs från en pipe "borta" - den buffrar det inte i minnet på något sätt även efter att man läst ut det?

1
Bevaka tråden