QProcess::setStandardOutputFile only creates 0kb File - qt

I'm using a simple QProcess-Project on a WindowsXP-Machine:
QString program = "U:\\ffmpeg.exe";
QStringList arguments;
arguments << "-i" << "U:\\clock.avi" << "U:\\tmp_jpeg\\foo-%03d.jpeg";
process.setStandardOutputFile("U:\\log.txt", QIODevice::Append);
process.start(program, arguments);
The Process works just fine, ffmpeg creates all the files i want to. But the log-File keeps completely empty. The same happens when I want to write the standard-output at qDebug()...
Why does this happen and how can I fix it?

This happens because usually processes print into two files: "standard output" file and "standard error" file. Programmer can manually decide which file to output to (they're accessed via std::cout and std::cerr). The rule of thumb is to print to stdout the actual result of the program, and to stderr - errors, diagnostics etc.
I run ffmpeg and it so happens, that it prints nothing to stdout (probably, reserving it for special mode, where encoded file is printed there), and all text messages are printed to stderr. So you should use setStandardErrorFile() function to capture the output.

Related

tail -f did not continue output the new lines added using vi

When I invoked "tail -f myfile.txt", the new line added using the following command output the new line, but not the line added/saved using vi. Does anyone know why ?
$echo "this is new line" >> myfile.txt
Thanks.
It has something to do w/the fact that while you are editing the file, vi keeps your changes in a second file (.myfile.txt.swp in this case).
When you save the changes, it's likely that vi is replacing the original file w/the second file. This means the file that tail was watching is no longer valid.
To prove this, try your echo command after saving the file with vi. When you do that, the output won't be displayed by tail.
The tail program opens a file, seeks to the end, and (with "-f") waits, then checks again if that open file has anything new to read.
vi does not append to a file. It makes a copy, (not a "swap", which is something else altogether) writes it out, and then moves the new file to have the same name as the old file.
tail is still watching the old file, not looking up a file by that file name every time.
In addition, tail uses the location in the file, so if you delete 10 characters and add 15, the next loop of 'tail' will emit the next 5 it thinks are new because they are after its placeholder.
Run 'tail --follow=name ...' to get tail to look up the file every loop by name, instead of watching the location on disk of a file it opens at start.

how to put input and output file in qtcreator

I wrote a very simple code using qtcreator It's a console application and I want to set up input and output text file, so qtcreator get's inputs form input file(not console) and save the output in output file is there any kind of option in qtcreator that can specify input and output file
If your program is already working by reading from console and writing to console using stdin and stdout, you just have to use console redirects.
You need to start your program from a command line using :
echo input.txt | myprogram.exe > output.txt
(windows)
cat input.txt | myprogram > output.txt
(unix)
Unfortunately, there is no possibility to redirect stdin and stdout from Qt Creator run options, AFAIK. You have to start the program yourself from the command line
You may try this for C++.
stringstream fcin(R"(1
3
1 2 3)");
istream cin(fcin.rdbuf());
int n;
while (cin >> n) {
cout << n << " ";
}

Qprocess and command MSDOS

I want execute a commande line with QProcess :
QString elf_path=C:\\files\\file.elf;
QString appli = "readelf.exe -a "+elf_path+" >>C:\\work\\essai.txt";
QProcess *process = new QProcess();
process->execute(appli);
but QT display this error :
readelf: Error: '>>C:\work\essai.txt': No such file
Can you help me ?
The QProcess::execute command will take the first parameter as the executable and pass each of the next parameters as arguments to that executable. So the error is because the readelf executable is receiving ">>C:\work\essai.txt" as an argument.
There is more than one solution to fix this.
Rather than redirecting the output to the text file, you could read the output from the readelf command (readAllStandardOutput), open a file essai.txt from Qt and append the output yourself. You should probably call waitForFinished() before retrieving the output.
Alternatively, there's a function in QProcess called setStandardOutputFile which takes a filename to redirect the output from the process to that file, which may be easier: -
QProcess* proc = new QProcess;
QString appli = "readelf.exe -a " + elf_path;
proc->setStandardOutputFile("C:\\work\\essai.txt", QIODevice::Append);
proc->start(appli);
Finally, you could create a shell script and call that with your parameters where the shell script would know that the final input parameter is to use for the output redirection.
QProcess::execute is static method. You should not create instance of QProcess in your case. Try next code
const QString path2exe = "readelf.exe";
QStringList commandline;
commandline << "-a";
commandline << elfPath;
commandline << "c:\\work\\essai.txt"
QProcess::execute( path2exe, commandline );
It looks like readelf is seeing your redirection as another file, which is valid since readelf can handle more than one on the command line.
Hence, the Qt process stuff is not handling redirection as you expect.
Within a shell of some sort, the redirections are used to set up standard input/output (and possibly others) then they're removed from the command line seen by the executable program. In other words, the executable normally doesn't see the redirection, it just outputs to standard output which the shell has connected to a file of some sort.
In order to fix this, you'll either have to run a cmd process which does understand redirection (passing the readelf command as a parameter) or use something like the method QProcess::readAllStandardOutput() to get the output into a byte array instead of writing to a temporary file.

Command sent twice via Expect

I have written an Expect script that logs into to a remote system, executes some commands in a sequence and captures the output in a log file.
Everything is happening fine except the fact that when I check the log file, some commands appear to be sent twice such that, the next command to be sent, appears in the middle of the output of the previous one. It is also sent again on detecting the prompt (which is the correct execution). Also, this issue does NOT occur in all cases, which is even more baffling.
I would like to add that I have customized the prompt to include this " ---> ". This is for easier output parsing by another script.
Here's the expect code,
set prompt "(]|%|#|>|\\$)"
# go to bash shell
expect -re $prompt
send "/bin/bash\r"
# customize the prompt
expect -re $prompt
send "PS1=\"\\u#\\H ---> \"\r"
# set new prompt into variable
expect -re $prompt
set newPrompt " ---> "
# opens file containing command list
set commFile [open commands.txt]
# reads each line containing commands from file, stores it in "$theLine" variable and sends it.
while {[gets $commFile theLine] >= 0} {
expect "$newPrompt"
send "$theLine\r"
}
close $commFile
This is how my output appears.
"prompt --->" command1
----output----
----output----
command2
----output----
----output----
"prompt --->" command2
----output----
----output----
Hope you get the idea.
I don't understand this behaviour nor was I able to find any solutions to this elsewhere. Any ideas?
There's a bit of a logic problem: after you send PS1=... you expect the old prompt. Then inside the loop you expect the new prompt before sending another command. Does this help?
send "PS1=\"\\u#\\H ---> \"\r"
set newPrompt { ---> $}
expect -re $newprompt
set commFile [open commands.txt]
while {[gets $commFile theLine] >= 0} {
send "$theLine\r"
expect -re "$newPrompt"
}

Running C++ program multiple times

I have a C++ program which I need to run it multiple times.
For example:-
Run ./addTwoNumbers 50 times.
What would be a good approach to solve this problem?
In POSIX shells,
for i in {1..50} ; do ./addTwoNumbers ; done
If this is code you are writing, take the number of times you want to "run" as an argument:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
int numTimes = 1;
if (argc > 1)
{
numtimes = atoi(argv[1]);
}
for (int i = 0; i < numTimes; i++)
{
// Your code goes here
}
}
(Note this doesn't do any sanity checking on the input, but it should point you in the right direction)
The way you were asking the question indicated that you had a finished binary. You want to run it as if it was from the command line. The forward slash, to me, is a clue that you are a Unix like operating system user. Well, that, and the fact that this post is tagged "Unix", which I just saw after writing the below. It should all be applicable.
The scheme of using the shell is probably the simplest one.
man bash tells you how to write a shell script. Actually we need to figure out what shell you are using. From the command line, type:
echo $SHELL
The response I get is
/bin/bash
Meaning that I am running bash. Whatever you get, copy down, you will need it later.
The absolutely lowest knowledge base is to simply create a file with any standard text editor and no suffix. Call it, simply (for example) run50.
The first line is a special line that tells the unix system to use bash to run the command:
#! /bin/bash
(or whatever you got from echo $SHELL).
Now, in the file, on the next line, type the complete path, from root, to the executable.
Type the command just as if you were typing it on the command line. You may put any arguments to your program there as well. Save your file.
Do you want to run the program, and wait for it to finish, then start the next copy? Or do you want to start it 50 times as fast as you can without waiting for it to finish? If the former, you are done, if the latter, end the line with &
That tells the shell to start the program and to go on.
Now duplicate that line 50 times. Copy and paste, it is there twice, select all, and then paste at the end, for 4 times, again for 8, again for 16, and again for 32. Now copy 18 more lines and paste those at the end and you are done. If you happen to copy the line that says #! /bin/bash don't worry about it, it is a comment to the shell.
Save the file.
From the command line, enter the following command:
chmod +x ./filenameofmyshellcommand
Where you will replace filenameofmyshellcommand with the name of the file you just created.
Finally run the command:
./filenameofmyshellcommand
And it should run the program 15 times.
If you are using bash, instead of duplicating the line 50 times, you can write a loop:
for ((i=1;i<=50;i++)) do
echo "Invocation $i"
/complete/path/to/your/command
done
I have included a message that tells you which run the command is on. If you are timing the program I would not recommend a "feelgood" message like this. You can end the line with & if you want the command to be started and the script to continue.
The double parenthesis are required for this syntax, and you have to pay your syntax.
for ((i=1;i<=50;i++)) do echo "invocation $i" & done
is an interesting thing to just enter from the command line, for fun. It will start the 50 echos disconnected from the command line, and they often come out in a different order than 1 to 50.
In Unix, there is a system() library call that will invoke a command more or less as if from the terminal. You can use that call from C++ or from perl or about a zillion other programs. But this is the simplest thing you can do, and you can time your program this way. It is the common approach in Unix for running one program or a sequence of programs, or for doing common tasks by running a series of system tools.
If youy are going to use Unix, you should know how to write a simple shell script.
int count=0;
int main()
{
beginning:
//do whatever you need to do;
int count++;
if (count<=50);
{
goto beginning;
}
return 0;
}

Resources