fwrite() doesn't write the full string - c++

fwrite only writes 8 bytes, The file should contain "Hello, World!" however when I open it, it shows "Hello, W"
FILE* f = fopen("file.txt", "w");
const char* b = "Hello, World!\n";
fwrite(b, sizeof(char), sizeof(b), f);
fclose(f);
I've googled "fwrite doesn't write the full string" but I couldn't find something similar to my problem.

sizeof(b) returns the size of the pointer, not the length of the string. You could use strlen to get it though:
fwrite(b, sizeof(char), strlen(b), f);
// Here ----------------^

Related

Rcpp doesn't seem to read a binary file properly

I am trying to read a binary file using fread() and Rcpp seems to be able to read the file, given ftell() returns the proper size. When I try to print the first byte, it either returns a ☐ or nothing at all. Then RStudio crashes. This code runs perfectly fine in VSCode, but not through Rcpp.
This is how I am trying to read the file.
inline void readFile(string filePath){
//read a file using the C fopen function and store to fileData
FILE* file = fopen(filePath.c_str(), "rb");
if (file == NULL){Rcpp::stop("Cannot open file");}
//find size and print it to console
fseek(file, 0, SEEK_END);
int sizeOfFile = ftell(file);
if (sizeOfFile < 1 || sizeOfFile == NULL){Rcpp::stop("Bad File size");}
Rcpp::Rcout << "File size: " << sizeOfFile << endl;
fileData = (char*)malloc(sizeof(char*)*sizeOfFile);
rewind(file);
fread(fileData, sizeOfFile, 1, file);
fclose(file);
arrayPointer = fileData;
end = fileData + sizeOfFile;
if(arrayPointer == NULL){Rcpp::stop("arrayPointer is null");}
Rcpp::Rcout << "ArrayPointer: " << *(uint8_t*)&arrayPointer[0] << endl; //crashes here
// Rcpp::Rcout << "File size: " << sizeOfFile << endl;
}
If I comment out where I print the first value in arrayPointer then program crashes in the next line after I call this function.
const_array_iterator(string filePath) {
//set up the iterator
readFile(filePath);
//read first 28 bytes of fileData put it into params -> metadata
uint32_t params[7]; //Crashes here too
memcpy(&params, arrayPointer, 28);
arrayPointer+=32; //first delimitor is 4 bytes
Rcpp::Rcout << "Copied params" << endl;
magicByteSize = params[0];
rowType = params[1];
nRows = params[2];
colType = params[3];
nCols = params[4];
valueWidth = params[5];
oldIndexType = params[6];
memcpy(&value, arrayPointer, valueWidth);
arrayPointer += valueWidth;
memcpy(&newIndexWidth, arrayPointer, 1);
arrayPointer++; //this should make it point to first index
}
My R code
library(Rcpp)
library(RcppClock)
library(RcppEigen)
sourceCpp("src\\playground.cpp") # The file the previous code blocks belong to
iteratorBenchmark(10, 10, 5.0)
This code is for use in a custom iterator, and I think it will work fine if these issues are fixed. I tried using an ifstream, but ran into similar issues. I have tried running this on linux as well as windows (WSL), but neither seem to work. I know the file is being read, as ftell() returns the correct amount of bytes. The data just seems to not be read properly from the file.

Why returned FILE* retains data when command in popen() fails

I am working on a program which uses popen() to find a file. Then copies the data in stream returned by popen() into a char array and prints it.
#include <iostream>
#include <cstdio>
#include <cstring>
int main()
{
char command[1024];
char ch = 'a';
FILE* pf;
while(ch < 'd')
{
sprintf(command, "find /home/ypatil/interest -name \\%c.out", ch);
std::cout << std::endl << command << std::endl;
pf = popen(command, "r");
if(pf)
{
char src[256];
fgets(src, 256, pf);
std::cout << std::endl << "pf = " << src << std::endl;
}
pclose(pf);
++ch;
}
return 0;
}
Now, I am doing this in loop and I found out that if file program is searching doesn't exist, then file stream pf retains its old value. Only a.out file exists on my system. So, the output of this program is -
find /home/ypatil/interest -name \a.out
pf = /home/ypatil/interest/a.out
find /home/ypatil/interest -name \b.out
pf = /home/ypatil/interest/a.out
find /home/ypatil/interest -name \c.out
pf = /home/ypatil/interest/a.out
So, you can see that find is searching for different files and only a.out exists. So, it will fail for other files. But, still pf retains its data in every iteration. I want to know why it retains value of FILE * returned by popen in previous iterataion.
Thank you.
Shoudn't it be NULL when find fails?
No, it should be a valid FILE * embodying the piped output of the find process. If the process doesn't produce any output, reading it will produce an immediate EOF. Starting the find process isn't failing here: it is just not finding anything.
Unclear why you think otherwise.

ciphertext length is not a multiple of block size in cryptopp

My program could encrypt text and save it in a file, and decrypt the cipher text after getting from the file.
But I keep on getting this error
terminate called after throwing an instance of 'CryptoPP::InvalidCiphertext'
what(): StreamTransformationFilter: ciphertext length is not a multiple of block size
While reading data from file i am getting file size as ciphertext length but content size is less what might be the wrong.
code:
std::string key = "0123456789abcdef";
std::string plaintext = "name macmilan age 24 ciy bonn country germany";
std::string ciphertext;
std::string decryptedtext;
CryptoPP::AES::Encryption aesEncryption((byte *)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::ECB_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption);
CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink( ciphertext ) );
stfEncryptor.Put( reinterpret_cast<const unsigned char*>( plaintext.c_str() ), plaintext.length() + 1 );
stfEncryptor.MessageEnd();
CryptoPP::AES::Decryption aesDecryption((byte *)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::ECB_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption);
std::cout << "ciphertext Text:"<<ciphertext.c_str()<<"length"<<ciphertext.length()<< std::endl;
FILE *ptr = fopen("temp.txt", "w");
if(ptr){
fprintf(ptr, "%s",ciphertext.c_str());
fclose(ptr);
ptr = NULL;
}
ptr = fopen("temp.txt", "r");
if(ptr){
fseek(ptr, 0, SEEK_END);
size_t size = ftell(ptr);
std::cout << "file size"<<size<< std::endl;
char* temp = new char[size];
rewind(ptr);
fscanf(ptr,"%s",temp);
ciphertext = temp;
delete[] temp;
ptr = NULL;
}
std::cout << "ciphertext Text:"<<ciphertext.c_str()<<"length"<<ciphertext.length() << std::endl;
try{
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
stfDecryptor.Put( reinterpret_cast<const unsigned char*>( ciphertext.c_str() ), ciphertext.size() );
stfDecryptor.MessageEnd();
}
catch(CryptoPP::Exception &e)
{
std::cout << "Decrypted Text:"<<e.what();
}
std::cout << "Decrypted Text: " << std::endl;
std::cout << decryptedtext;
std::cout << std::endl << std::endl;
system("pause");
return 0;
output:
ciphertext Text:î4¬■◄vqù┼Ä╢óΣ*₧z┐É;'!ìy─ªú√#╕╡Oh∙2♠ε\→ktáäì╘aÄδ▌length48
file size48
ciphertext Text:î4¬■◄vqù┼Ä╢óΣ*₧z┐É;'!ìy─ªú√#╕╡Oh∙2♠ε\length37
Decrypted Text:StreamTransformationFilter: ciphertext length is not a multiple o
f block sizeDecrypted Text:
name macmilan ag
In encryption various characters may appear including null (0). So when you write encrypted string in file you write null too.
When you are retrieving encrypted value reader gets null character and assumes that string has been terminated. so it will be shorter.
For resolve you have to use coding like Base64 or MD5 or open file and read in binary mode
You probably want to read and write your file in binary mode - use "wb" and "rb" in your calls to fopen.
Also you might want to use fwrite and fread. fscanf will stop on whitespace which wouldn't help you.
When reading and writing binary files, the mode parameter to fopen must be "rb" or "wb", otherwise non-printable characters in the file may be interpreted as control characters. Here it looks like you have a Ctrl-Z (hex 0x1a) in your data, which is an end-of-file marker in a text file.

Send raw data to printer programmatically

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";
}

Manipulating result from "system" call in C++ program

Say that I execute some command to run in the terminal within a C++ program. For instance:
int main(){
std::system("./myprog");
return 0;
}
Assume that myprog produces some output that is printed to the console. Can I make use of this output within my C++ program? For example:
int main(){
some_var = std::system("./myprog");
if (some_var == "something")
// Do something.
return 0;
}
Any help would be very much appreciated. Thanks again.
You need to use the popen function:
FILE *fp = popen("./myprog", "r");
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp))
{
std::cout << "Output from program: " << buffer << '\n';
}
pclose(fp);