I wish to print some text directly to a network printer from my c++ code (I am coding with xcode 4). I do know that everything on unix is a file and believe that it would not be impossible to redirect the text using fstream method in c++ to the printer device file. The only problem is I don't know the device file in /dev associated with my network printer.
Is it possible to achieve printing using fstream method? Something like
std::fstream printFile;
printFile.open("//PATH/TO/PRINTER/DEV", std::ios::out);
printFile << "This must go to printer" << std::endl;
printFile.close();
And, if so
How to obtain the file in /dev corresponding to a particular printer?
Thanks in advance,
Nikhil
Opening and writing directly to a file used to be possible back in the days of serial printers; however, this is not the approach available today.
The CUPS daemon provides print queuing, scheduling, and administrative interfaces on OS X and many other Unix systems. You can use the lp(1) or lpr(1) commands to print files. (The different commands come from different versions of print spoolers available in Unix systems over the years; one was derived from the BSD-sources and the other derived from the AT&T sources. For compatibility, CUPS provides both programs.)
You can probably achieve something like you were after with popen(3). In shell, it'd be something like:
echo hello | lp -
The - says to print from standard input.
I haven't tested this, but the popen(3) equivalent would probably look like this:
FILE *f = popen("lp -", "w");
if (!f)
exit(1);
fprintf(f, "output to the printer");
I recommend testing some inputs at the shell first to make sure that CUPS is prepared to handle the formatting of the content you intend to send. You might need to terminate lines with CRLF rather than just \n, otherwise the printer may "stair-step" the output. Or, if you're sending PDF or PS or PCL data, it'd be worthwhile testing that in the cheapest possible manner to make sure the print system works as you expect.
Related
Kernel: 3.12.30-AM335x-PD15.2.1 (by PHYTEC)
My application requires editing a text file on run time and using it contents next time it powers on. So I created a text file in which I write a simple text, "Disable" or "Enable" using the program I have written with QT C++.
What I realized is, after the program writes the simple text, if I use the command "reboot" on bash, and wait for the program to reboot before I power off the the system (by plugging off its cable), "cat TextFile.txt" command yields "Enable" or "Disable", whichever the program has last written correctly.
However if I don't do a reboot and power the system off right away, and then power on again, the text file remains but the contents are deleted, so "cat TextFile.txt" yields nothing.
I tried to do the same manually, using the below methods:
Method 1:
echo Disable > TextFile.txt
reboot
.....wait for it to reboot
cat TextFile.txt
The results is "Disable".
Method 2:
echo Disable > TextFile.txt
.. power off by plugging off the cable
.. power on the system
cat TextFile.txt
No resulting text..
I simply don't want to have to reboot the system for the files to be saved. So I would be happy with executing commands within my QT C++ program to save everything without a reboot; but I do not know the operating system very well, therefore I do not know what is it that I should do to be able to do this.
This is my code my by the way:
QFile file(filename);
// Trying to open in WriteOnly and Text mode
if(!file.open(QFile::WriteOnly |
QFile::Text))
{
qDebug() << " Could not open file for writing";
}
// To write text, we use operator<<(),
// which is overloaded to take
// a QTextStream on the left
// and data types (including QString) on the right
QTextStream out(&file);
out << "Enable";
file.flush();
file.close();
As your experiement on the shell has shown this is not strictly a c++ or Qt matter, the file is just not written to disk right away.
The system setup is likely using delayed writing to optimize disk access times, i.e. first writing into in-memory buffers and writing to actual disk every once in a while.
You might want to tune that if you have other programs that write files and expect power loss as a realistic scenario.
Now, for the Qt program in question, you could try using QSaveFile instead of QFile, its commit() asks the system to actually sync to disk.
On my home Linux laptop, I like to write wrapper programs and GUI helpers for things I use frequently. However, I don't like Bash scripting very much, so I do a lot of stuff in C++. However, a lot of times, this requires me to use the system() function from the cstdlib.
This system() command is awesome, but I wanted a way to call system() and receive the stdout/stderror. The system() command only returns the return code from the command. So, in a Bash script, one can do:
myVar=$(ls -a | grep 'search string')
echo $myVar
and myVar will output whatever the stdout was for the command. So I began writing a wrapper class that will add a pipe-to-file to the end of the command, open the file, read all of the piped stdout, and return it as either one long string or as a vector of strings. The intricacies of the class are not really relevant here (I don't think anyway), but the above example would be done like this:
SystemCommand systemCommand;
systemCommand.setCommand("ls -a | grep \'search string\' ");
systemCommand.execute();
std::cout << systemCommand.outputAsString() << std::endl;
Behind the scenes, when systemCommand.execute() is called, the class ensures that the command will properly pipe all stdout/stderr to a randomly generated filename, in the current working directory. So for example, the above command would end up being
"ls -a | grep 'search string' >> 1452-24566.txt 2>&1".
The class then goes attempts to open and read from that file, using ifstream:
std::ifstream readFromFile;
readFromFile.open(_outputFilename);
if (readFromFile.is_open()) {
//Read all contents of file into class member vector
...
readFromFile.close();
//Remove temporary file
...
} else {
//Handle read failure
}
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory? If so, what would be a way to make it more robust (specifically on Linux)?
A side/secondary question: Is there a very simplified way to achieve what I'm trying to achieve without using file pipes? Perhaps some stuff available in unistd.h? Thanks for your time.
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory?
Yes.
Mount a USB thumb drive (or some other removable media)
cd to the mount
Execute your program. While it's executing, remove the drive.
Watch the IO error happen.
There's a ton of other reasons too. Filesystem corruption, hitting the file descriptor limit, etc.
If so, what would be a way to make it more robust (specifically on Linux)?
Make temporary files in /tmp, whose entire purpose is for temporary files. Or don't create a file at all, and use pipes for communication instead (Like what popen does, like harmic suggested). Even so, there are no guarantees; try to gracefully handle errors.
Can ofstream be used to write on a printer?
eg:
string nameOfPrinter = "xyz";
ofstream onPrinter(nameOfPrinter);
onPrinter << "Printing.... ";
If I do as above will I get the output by the printer (on the paper) ?
If not, why I won't get the output? Please suggest a way to print using a printer.
I am targeting the Windows platform (32bit)
If you happen to have your printer associated with LPT1 and a printer which support formfeeds.
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
ofstream printer ("LPT1");
if(!printer)
{ return 1;
}
printer.puts("Test Test Test\n");
printer.putc('\f');
printer.close();
return 0;
}
LPT1 is also a file name in windows. But as known it is a reserved filename. So it will not be possible to have more than one file with the name LPT1. And this file is already managed by windows.
See for reserved filenames
Yes you can, Your code should be:
ofstream printer;
printer.open("lpt1");
I believe it's case sensitive(not sure "lpt1" or "LPT1"). Also, you'll need to write a page eject command.
EDIT:
LPT (Line Print Terminal) is name of the parallel port interface on IBM PC-compatible computers. Over the years, the parallel port interface has decreased use because of the rise of Universal Serial Bus.
In DOS, the parallel ports could be accessed directly on the command line. For example, the command type c:\autoexec.bat > LPT1 would direct the contents of the autoexec.bat file to the printer port(recognized by the reserved word LPT1"). A PRN device was also available as an alias for LPT1.
Microsoft Windows still refers to the ports in this manner in many cases, though this is often fairly hidden.
In the Linux operating system the first LPT port is available via the filesystem as /dev/lp0.
To write to a printer, one should simply open the printer as if it were a file (the printer name is system-dependent; on Windows machines, it will be lpt1 or prn, while on unix machines, it will be something like /dev/lp), then write whatever text has to be written.
Sample program could be as simple as:
std::ofstream print;
print.open("LPT1");
if (!print)
return 0;
print << data;
print.close();
How would the file stream know the difference between the name of a printer and a file that just happened to share the name of a printer? So no; you can't print to a printer by specifying the name of a printer.
Printing in Win32 is not a trivial task. You can't simply shove some characters at a printer; it needs to know about page layout, fonts, etc. Basically, the way to do it from Win32 is to "draw" to the printer with GDI commands. Beginner-level info can be found here.
Correction: apparently, you can stream output to the printer with a stream. However, it requires that the user has enabled some legacy functionality, so it isn't necessarily always available.
I'm working with the output of a program to which I have the C++ source code. The program sends output to stderr, and I need to know where/how the output is calculated in the source code.
I know that one form to send something to stderr is
std::cerr << "foo";
I use grep to see if this form is used, but I can't find it.
I know that is written to stderr because when I run the program I obtain the output in this form:
./program 2> file-with-info.txt
Are there any other ways for output to be sent to stderr? Can anybody suggest patterns I might grep for to find where this output is being sent?
It's not
cerr < "foo"
but
cerr << "foo"
You can try to grep for clog (redirected to the standard error stream) too :
clog <<
You can also search for stderr and perror which are the old C ways to output to standard err
std::cerr, std::clog and stderr all three denote the standard error stream. The first two are the (unbuffered and buffered) C++ interfaces, the third is the old C stdio interface. perror also writes to standard error.
Depending on the platform, there may be more ways to output to standard error, such as writing to the file descriptor 2 on Unix. (If you're lucky, you can grep for the symbolic constant STDERR_FILENO.)
The most reliable thing to do would be to hook the OS function that writes out and if it's writing to the Standard error output, then break/print callstack. If you settle for anything else, then there's a dozen ways it can be output without you finding that exact string.
My Code:
std::ofstream m_myfile,
m_myfile.open ("zLog.txt");
m_myfile << "Writing this to a file " << " and this " << endl;
when this C++ Program runs, I have another program that needs to read this file. The problem is that the file is locked by C++ and I cannot read it from the other program. I know there is something I have to do where I write the code someway in the C++ Program where it allows sharing. Can someone write exactly what I need. I have googled this to death and still cannot get this to work.
Some people say close the file, before the other program reads it. I cannot do this, the file needs to be open.
You need to open the file with sharing enabled. Use the following overload of the open method:
void open(const char *szName, int nMode = ios::out, int nProt = filebuf::openprot);
and pass the appropriate share mode as nProt:
filebuf::sh_compat: Compatibility share mode
filebuf::sh_none: Exclusive mode; no sharing
filebuf::sh_read: Read sharing allowed
filebuf::sh_write: Write sharing allowed
There is also an overload of the ofstream constructor that takes the same arguments.
The sharing is going to be controlled at the OS level. So you need to look at the API for your OS and figure out how to turn read-write sharing on.
Note: you still probably won't get the results you want because there will be caching and buffering issues and what you think was written to the file may not actually be there.
If you want to share information between two processes, use named pipes or sockets. Both are available on just about every OS.
Use filebuf::sh_write while opening the file.
Other option is to use sockets. Check out this stackoverflow question: Is there a way for multiple processes to share a listening socket?