I want to send to my printer data I load from a file so that it can print a barcode (ITF 2/5).
if I use the command prompt and do "print c:\test lpt1", it works like a charm and it prints the expected barcode. However, when I try to do this programmatically, the printer fails to provide said barcode. Readable text works fine, it's (so far) exclusively an issue I have with the barcode printing.
I have the following code in which ( I thought ) I would be sending a printer raw data (not rendered in any way) so that the printer can decide how to decode those bytes I'm sending to it.
std::FILE* fd = fopen("c:\\test", "rb");
std::fseek(fd, 0L, SEEK_END);
int size = std::ftell(fd);
std::fseek(fd, 0L, SEEK_SET);
int beginning = std::ftell(fd);
if(fd == NULL)
{
std::cerr << "Error opening file\n";
return;
}
char* buffer = (char*)malloc(size);
std::fread(buffer, 1, size, fd);
std::ofstream output("lpt1", std::ios_base::out);
output << buffer;
My only guess (and a blind one, at that) is that I am mistakingly assuming the ofstream is receiving raw data when it's not... and I don't know why or how to solve that.
I am not asking for a 'do my homework for me' answer (Although a very clear and epic answer would be awesome) but at least if you could point me in the right way of why I am not getting the expected result, I would be really grateful. Even some keywords for searching and researching on my own would be great, too. I honestly have no idea of what I am doing wrong.
This is some new code I tried because of a suggestion to use IOStreams, again, I get NOT the desired result when I try to edit the content of input.rdbuf().
static void ImprimirArchivo(unsigned char* path)
{
std::ifstream input((char*)path, std::ios::binary);
std::ofstream output("lpt1", std::ios::binary);
std::istreambuf_iterator<char> eos;
std::istreambuf_iterator<char> streamInputIterator (input.rdbuf());
bool codeBarStarted = false;
int iterationsCounter = 0;
while(streamInputIterator!=eos)
{
if(*streamInputIterator == 0x14)
{
output << '1d';
output << '6b';
output << '05';
output << '30';
codeBarStarted = true;
}
else
{
output << *streamInputIterator;
}
if(codeBarStarted)
{
iterationsCounter++;
if(iterationsCounter == 10)
{
output << 0x00;
codeBarStarted = false;
iterationsCounter = 0;
}
}
streamInputIterator++;
}
Please note that when I do
if(*streamInputIterator == 0x14)
{
output << '1d';
output << '6b';
output << '05';
codeBarStarted = true;
}
If I replace that with
if(*streamInputIterator == 0x14)
{
output << 0x1d;
output << 0x6b;
output << 0x05;
codeBarStarted = true;
}
the corresponding output is still wrong, but wholly different. When I use 0xXY, what's printed is the decimal number as in: output << 0x1d makes the printer print "29" (text).
A short in the dar: Open both files in binary mode, in particular std::ofstream:
std::ofstream output("lpt1", std::ios::binary);
(there is no need to also specify std::ios::out because it is added when opening a std::ofstream anyway but you could use std::ios::out | std::ios_binary if you want).
Personally, I would use IOStreams for both the input and the output:
std::ifstream input("c:\\test", std::ios::binary);
if (input) {
std::ofstream("lpt1", std::ios::binary) << input.rdbuf();
}
else {
std::cerr << "ERROR: failed to open 'c:\\test' for reading\n";
}
Related
Originally was trying to read data using char* but switched to string cause was getting behavior as if there was a missing null terminator. made the problem minimal below but still getting very weird output
int main(int argc, char * argv[]){
// file one: flightData
std::ifstream inFile1(argv[1]);
if (!inFile1.is_open())
{
std::cout << "Could not open the file 1." << std::endl;
return -1;
}
// file two: flightPlans
std::ifstream inFile2(argv[2]);
if (!inFile2.is_open())
{
std::cout << "Could not open the file 2." << std::endl;
return -1;
}
//File three: output
std::ofstream outputfile(argv[3]);
if (!outputfile.is_open())
{
std::cout << "Could not open the output file" << std::endl;
return -1;
}
std::string buffer;
getline(inFile1, buffer);
std::cout<<buffer<<std::endl;
while (getline(inFile1, buffer)) {
std::cout<<buffer;
std::cout<<"help";
}
// flightPlanner system(inFile1);
// system.printF();
// system.planFlights(inFile2,outputfile);
return 0;
}
output is
4
helpDallas|Austin|50|50help
which i'm pretty sure is incorrect, interestingly when i add endl to cout buffer it gives me output i would expect not really sure whats going on
inFile1
4
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
When i run in debugger i get the output i expect:
4
Dallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50help
any idea what could be going on?
Do you need flushing your stdout?
std::cout << std::flush;
Any chance your shell ate your outputs?
Try pipping the output to "cat -A":
./a.out | cat -A
(Drive by comment - I may not know what I'm talking about ^_^)
I have created a pseudo terminal in C++ using the following code:
int main(int, char const *[])
{
int master, slave;
char name[1024];
char mode[] = "0777"; //I know this isn't good, it is for testing at the moment
int access;
int e = openpty(&master, &slave, &name[0], 0, 0);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
if( 0 != unlockpt(slave) )
{
perror("Slave Error");
}
access = strtol(mode, 0, 8);
if( 0 > chmod(name, access) )
{
perror("Permission Error");
}
//std::cout << "Master: " << master << std::endl;
std::printf("Slave PTY: %s\n", name);
int r;
prompt = "login: ";
while(true)
{
std::cout << prompt << std::flush;
r = read(master, &name[0], sizeof(name)-1);
checkInput(name);
name[r] = '\0';
std::printf("%s", &name[0]);
std::printf("\n");
}
close(slave);
close(master);
return 0;
}
It works pretty well in the sense that from another terminal, I can do:
printf 'username' > /dev/pts/x
and it will appear and be processed as it should.
My question is: when I try to use screen, nothing appears on the screen terminal. Then when I type, it comes through to my slave 1 character at a time.
Does anyone know why this is? Or how I can fix it.
I can provide more detail if required.
Thank you :)
Because you're not flushing the buffer after you use printf.
As pauls answer already suggest you need to flush the buffer.
To do so you can use the tcflush function.
The first argument is the int of the file descriptor and the second can be one of the following:
TCIFLUSH Flushes input data that has been received by the system but
not read by an application.
TCOFLUSH Flushes output data that has been written by an application
but not sent to the terminal.
TCIOFLUSH Flushes both input and output data.
For more information see: https://www.ibm.com/docs/en/zos/2.3.0?topic=functions-tcflush-flush-input-output-terminal
I'm writing a Web API, using CGI under linux. All is great, using gcc. I am returning an image (jpeg) to the host: std::cout << "Content-Type: image/jpeg\n\n" and now must send the binary jpeg image. Loading the image into a char* buffer and std::cout << buffer; does not work. I do get back an empty image. I suspect stdout stops on the first 00 byte.
I'm receiving from the web server a 200 OK with an incomplete image.
I was going to redirect to the file in an open folder on the device, but this must be a secure transfer and not available to anyone who knows the url.
I'm stumped!
The code snippet looks like this:
std:string imagePath;
syslog(LOG_DEBUG, "Processing GetImage, Image: '%s'", imagePath.c_str());
std::cout << "Content-Type: image/jpeg\n\n";
int length;
char * buffer;
ifstream is;
is.open(imagePath.c_str(), ios::in | ios::binary);
if (is.is_open())
{
// get length of file:
is.seekg(0, ios::end);
length = (int)is.tellg();
is.seekg(0, ios::beg);
// allocate memory:
buffer = new char[length]; // gobble up all the precious memory, I'll optimize it into a smaller buffer later
// OH and VECTOR Victor!
syslog(LOG_DEBUG, "Reading a file: %s, of length %d", imagePath.c_str(), length);
// read data as a block:
is.read(buffer, length);
if (is)
{
syslog(LOG_DEBUG, "All data read successfully");
}
else
{
syslog(LOG_DEBUG, "Error reading jpg image");
return false;
}
is.close();
// Issue is this next line commented out - it doesn't output the full buffer
// std::cout << buffer;
// Potential solution by Captain Obvlious - I'll test in the morning
std::cout.write(buffer, length);
}
else
{
syslog(LOG_DEBUG, "Error opening file: %s", imagePath.c_str());
return false;
}
return true;
As it's already been pointed out to you, you need to use write() instead of IO formatting operations.
But you don't even need to do that. You don't need to manually copy one file to another, one buffer at a time, when iostreams will be happy to do it for you.
std::ifstream is;
is.open(imagePath.c_str(), std::ios::in | std::ios::binary);
if (is.is_open())
{
std::cout << is.rdbuf();
}
That's pretty much it.
This boiled down to a much simpler block. I hard coded the imagePath for this example. Put this in your linux web server's cgi_bin folder, place a jpg in ../www_images/image0001.jpg and from your client call the web server via http:///cgi_bin/test and you return the image.
#include <stdio.h>
#include <iostream>
#include <fstream>
int test()
{
std::ifstream fileStream;
std::string imagePath = "../www_images/image0001.jpg"; // pass this variable in
// output an image header - CGI
syslog(LOG_DEBUG, "Processing GetImage, Image: '%s'", imagePath.c_str());
std::cout << "Content-Type: image/jpeg\n\n";
// output binary image
fileStream.open(imagePath.c_str(), std::ios::in | std::ios::binary);
if (fileStream.is_open())
{
std::cout << fileStream.rdbuf();
}
else
{
return 1; // error - not handled in this code
}
return 0;
}
ps: no religious wars on brackets please. ;)
The following C++ code is to read a txt file and then write the numbers of chars in each line and the number of all chars in the txt file.I use MS Visual Studio 2008.But something is wrong.Only the number of all chars is input into the txt files,but the numbers of each line are not input into the txt files.Now I cannot figure it out.Could someone give me some advice?Thanks a lot!
And my another question is what should I do to insert something in the middle of the txt file?
This is my Code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream inOut("copy.txt",ios::in | ios::out | ios::app);
if (!inOut)
{
cerr << "ERROR:cannot open file!" << endl;
return -1;
}
int cnt = 0;
char ch;
inOut.seekg(0);
while(inOut.get(ch))
{
cout.put(ch);
++cnt;
if ('\n' == ch)
{
ios::pos_type mark = inOut.tellg();
if (!inOut)
{
cerr << "ERROR!" << endl;
return -1;
}
inOut << cnt;
inOut.put(' ');
inOut.seekg(mark);
}
}
inOut.clear();
inOut << cnt << endl;
cout << "[" << cnt << "]" << endl;
}
The txt file before running:
The txt file after running:
The result in command line:
I don't know fstream's very well, but I think you want to change the way you are doing this. You can think of a file as a contiguous piece of memory. Appending on the end is easy, but inserting in the middle can be problematic. In particular, if you do insert something, then your seekg might not be valid.
I would recommend three strategies:
Understand what is going on currently (try closing file before seekg and see if anything gets written by the inOut << cnt;)
Read from one file, write to a different file -- this will most likely be more efficient and less complicated than trying to modify the file in place.
Read from source file, store and modify in memory, write out modified buffer to original file. For large files, this might be less efficient than #2, but it means you don't need two files on disk.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream inOut("copy.txt",ios::in | ios::out | ios::app);
if (!inOut)
{
cerr << "ERROR:cannot open file!" << endl;
return -1;
}
int cnt = 0;
int cntline=0;
char ch;
inOut.seekg(0);
while(inOut.get(ch))
{
cout.put(ch);
//++cnt it include '\n' it should put behind of "if"
if ('\n' == ch)
{ ios::pos_type mark = inOut.tellg();
if (!inOut)
{
cerr << "ERROR!" << endl;
return -1;
}
cntline=cnt-cntline; //add it to account the number of chars of each line
inOut.seekg(0,ios::end); //here!!!!!!!!!!!!!!!!!!!!!!!!!!! add this , the resault is finally right! the reason it's down here.
inOut << cntline;
cntline=cnt; // and here! it can assure the number of the chars of each line be right!
inOut.put(' ');
inOut.seekg(mark);
}
else
{
++cnt; // it's here!
}
}
inOut.clear();
inOut << cnt << endl;
cout << "[" << cnt << "]" << endl;
}
inOut.seekg(0,ios::end)
i'am not sure it,but you can take it a reference.
you open file with "ios::app",so the VS 2008 only allows you to add text start from the end of file (it won't happened in vc 6.0).
if the file is :
it's compile by
vs 2008
when get the first '\n' the file pointer is pointing to'vs 2008'(yes,it just like the common pointer point the string ). and i debug it then find a value of the stream object named _Wrotesome .its value is false!
so i think the compiler think the file pointer point at o const sting.so you just can't write anything whis this position. so i add the code inOut.seekg(0,ios::end);.now you
can write anything you want to this text!
wish this can help you !
I don't know why do you choose std::fstream as your tool. If std::fstream is not asked or necessary, I would like to provide a example to solve your problem. Here's some limitation:
a. I read all the file into memory in one ReadFile operation. If your file is large, you may replace it with a loop.
b. I suppose your line separator is '\n'.
c. I add [line_count] before the '\n', which look like better.
here's my code.
#include "windows.h"
#include "sstream"
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = ::CreateFile(L"C:\\Users\\wujian\\Desktop\\pingback - Copy.log", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE )
{
DWORD dwSize = ::GetFileSize(hFile, NULL);
if (dwSize)
{
char *pBuffer = new char[dwSize];
DWORD dwRead = 0;
::ReadFile(hFile, pBuffer, dwSize, &dwRead, NULL);
if (dwRead == dwSize)
{
std::stringstream ss;
int iPos = 0;
int iLine = 0;
while (iPos < dwSize)
{
if (pBuffer[iPos] == '\n')
{
ss << '[' << iLine << ']';
iLine = 0;
}
ss << pBuffer[iPos];
iPos ++, iLine ++;
}
ss << '[' << dwSize << ']';
::SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
DWORD dwWrite = 0;
::WriteFile(hFile, ss.str().c_str(), ss.str().length(), &dwWrite, NULL;
}
::CloseHandle(hFile);
}
}
return 0;
}
While reading a binary file using DJGPP on DOS this code hangs.
This happens when the fread call is made. If the call is removed then the program runs successfully.
The same code runs fine through Visual C++ 2008.
Has anyone experienced similar issues with djgpp ?
Am I missing out on something really simple ?
char x;
string Filename = "my.bin" ;
fp = fopen(Filename.c_str(),"rb");
if (fp == NULL)
{
cout << "File not found" << endl ;
}
if (fseek (fp, 0, SEEK_END) != 0)
{
cout <<"End of File can't be seeked";
return -1;
}
if ( (fileLength = ftell(fp)) == -1)
{
cout <<"Can't read current position of file";
return -1;
}
if (fseek (fp, 0, SEEK_SET) != 0)
{
cout <<"Beginning of File can't be seeked";
return -1;
}
if (fread(&x,sizeof(x),1,fp) != sizeof(x))
{
cout <<"file not read correctly";
return -1;
}
I don't see what 'fp' is. I just have to assume it's 'FILE * fp;'.
I don't see that you actually include < stdio.h >, and have to assume you do.
I don't see that you actually include < iostream > and declare 'using namespace std;', and have to assume you do.
I don't see what comes after the fread() call that could tell you if call succeeded.
Going through the process of actually reducing your faulty code to the absolute but complete minimum to reproduce the error is the first thing you should do when a piece of code has you dumbfounded.
It might (and usually does) turn out that the problem isn't even where you thought it is.
That being said, I'd try replacing
if (fread(&x,sizeof(x),1,fp) != sizeof(x))
{
cout <<"file not read correctly";
return -1;
}
with
int i;
if ( ( i = fgetc( fp ) ) == EOF )
{
perror( "File not read correctly" );
return -1;
}
x = (char) i;
cout << "Success, read '" << x << "'." << endl;
Using 'perror()' instead of homebrewn cout messages gives you additional information on the cause of any error. Using 'fgetc()' will show you that the file actually does contain what you think it does, and that your problems are not due to the somewhat uncommon use of fread() for a single byte.
Then report back.
fread takes a pointer as the first parameter. If you only have to read in one character, char x; is fine, but pass the address of x instead.
fread(&x,sizeof(x),1,fp) != sizeof(x)
and since sizeof char is always 1 (by definition) you can very well write:
fread(&x,1,1,fp) != 1