Rendering files from C++ Node.js addon - c++

I would like to render files in node.js from C++ addon.
I want to apply some file processing and render the output to the browser via node.js
Here is my C++ Code
std::ifstream in(filename, std::ios::binary);
in.seekg (0, in.end);
int length = in.tellg();
in.seekg (0, in.beg);
char * buffer = new char [length];
in.read (buffer,length);
in.close();
return buffer;
Following is the V8 code to add bindings for node.js, here buffer is the output from the above c++ code.
Local<Function> cb = Local<Function>::Cast(args[1]);
const unsigned argc = 1;
Local<Value> argv[argc] = {Local<Value>::New(String::New(buffer))};
cb->Call(Context::GetCurrent()->Global(), argc, argv);
This code works well for normal text files. I'm getting problem when reading text files which are having unicode characters.
For eg,
Original text file
test start
Billél
last
When receiving in node, I will get
test start
Bill�l
last
Similarly when reading a jpg, png files the output file is different than the original file.
Please help.

I was having problems with this as well. I found an implementation in the V8 examples from Google. The example I found that properly handles UTF8 encoded files is found here:
https://code.google.com/p/v8/source/browse/trunk/samples/shell.cc#218
I adapted the source to this:
const char* ReadFile(const char* fileName, int* fileSize)
{
// reference to c-string version of file
char *fileBuffer = 0;
// attempt to open the file
FILE* fd = fopen(fileName, "rb");
// clear file size
*fileSize = 0;
// file was valid
if(fd != 0)
{
// get size of file
fseek(fd, 0, SEEK_END);
*fileSize = ftell(fd);
rewind(fd);
// allocate file buffer for file contents
fileBuffer = (char*)malloc(*fileSize + 1);
fileBuffer[*fileSize] = 0;
// copy file contents
for (int charCount = 0; charCount < *fileSize;)
{
int charRead = static_cast<int>(fread(&fileBuffer[charCount], 1, *fileSize - charCount, fd));
charCount += charRead;
}
// close the file
fclose(fd);
}
return fileBuffer;
}
Also, make sure when you create a V8 string that you create a String::Utf8Value.
String::Utf8Value v8Utf8String(...);
Then to use the String::Utf8Value as a char* use the following function:
https://code.google.com/p/v8/source/browse/trunk/samples/shell.cc#91

Related

C++ GTKMM, getting a weird output in a text-buffer

I'm new to Gtkmm and trying to load a txt-file into a Text-Buffer. When I start my program I get a output like this: Output
My code for filling the Text-Buffers looks like this:
void ExampleGui::fill_buffers()
{
FILE *fp = fopen("/home/User/Documents/Gui/test1.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
char *line = NULL;
size_t len = 0;
char *output = NULL;
while ((getline(&line, &len, fp)) != -1) {
output = line;
}
fclose(fp);
if (line)
free(line);
m_refTextBuffer1 = Gtk::TextBuffer::create();
m_refTextBuffer1->set_text("Welcome!\nClick the button Show Text to start.");
m_refTextBuffer2 = Gtk::TextBuffer::create();
m_refTextBuffer2->set_text(Glib::convert_with_fallback(output, "UTF-8", "ISO-8859-1"));
}
How can I fix that wrong output and why do I get it?
The main problem here is the assignment output = line followed by free(line).
Because output points to the same memory as line that means output becomes invalid.
Either don't free the memory until you're done with the string, or duplicate the string in line (which the assignment doesn't do).

Writing file from zip file in C++

I need to unzip a file that I download from the internet, in C++. I've searched around for hours and I can't find anything.
For the moment I'm using libzip, and I can successfully read the file, I just have no idea on how to write it as files in a folder:
int unzipFile(std::string zipPath) {
//Open the ZIP archive
int err = 0;
zip* z = zip_open(zipPath.c_str(), 0, &err);
//Search for the file of given name
const char* name = "AvaloniaLauncher.exe";
struct zip_stat st;
zip_stat_init(&st);
zip_stat(z, name, 0, &st);
//Alloc memory for its uncompressed contents
char* contents = new char[st.size];
//Read the compressed file
zip_file* f = zip_fopen(z, name, 0);
zip_fread(f, contents, st.size);
zip_fclose(f);
//And close the archive
zip_close(z);
//Do something with the contents
printf(contents);
//delete allocated memory
delete[] contents;
return err;
}
I only found this snippet on a old thread from '12, so I would't wake that up again.
I now have the uncompressed contents of the file, but how would I go about on writing it?
Thanks.

Passing a char array reading from file to fopen() generating error as Invalid arguments

I tried to read file path and name into a char array from a configuration.txt file. Then passing the char array to fopen(). However, it is generating errors like invalid argument. Instead, if I directly passed the path same to what is in configuration.txt, it will succeed. The code is like:
FILE *FIDConfig = fopen(argv[1],"r"); // open configuration file; could be a .txt file
char inputfname[200], backgroundfname[200], outputfname[200];
fscanf(FIDConfig, "%s", inputfname); //int fscanf ( FILE * stream, const char * format, ... );
fscanf(FIDConfig, "%s", backgroundfname);
fscanf(FIDConfig, "%s", outputfname);
/* FILE WITH THE RAW DATA */
errno = 0;
FILE *FIDIN, *FIDOUT, *FIDBack; // inputfname = "./data.bin", backgroundfname = "./dbk.bin";
FIDIN = fopen(inputfname, "rb"); // if changed to FIDIN("./data.bin","rb") it works!
FIDBack = fopen(backgroundfname, "rb");

_read function is returning obsolete values for file handle

The block of code here runs fine till the _read function is called, after that it changes the value of file handle variable 'fh' for no reason.
std::string& xLogFile;
std::string& xBuffer;
struct _stat& xStatBuffer)
char *buffer;
buffer = (char *)malloc(sizeof(char) * xStatBuffer.st_size);
#define _O_RDONLY 0x0000 /* open for reading only */
int fh = 0, read_bytes =0;
fh = _open(xLogFile.c_str(), _O_RDONLY); // ToDo function deprecated should be changed to fstream
if (fh ==1)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't open the log file");
return true;
}
read_bytes = _read(fh,&buffer,xStatBuffer.st_size);
_close(fh);
if (read_bytes <= 0)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't read the log file");
return true;
}
buffer[read_bytes] = '\0';
xBuffer = buffer;
This is a block of code i am using to read from a file into a buffer, but it is failing at the _read function, where the value of file handle 'fh' changes after the call to the function.
Fix the code as below, buffer and not &buffer. You are overwriting the stack.
read_bytes = _read(fh,buffer,xStatBuffer.st_size);

C++ fwrite doesn't write to text file, have no idea why?

I have this code that basically reads from file and creates new file and write the content from the source to the destination file. It reads the buffer and creates the file, but fwrite
doesn't write the content to the newly created file, I have no idea why.
here is the code. (I have to use only this with _sopen, its part of legacy code)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
FILE* pfFile;
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
pfFile = fdopen(iFileId, "r");
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
// buffer = (char*) malloc (sizeof(char)*lSize);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
return false;
}
// copy the file into the buffer:
result = fread (buffer,lSize,1,pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
return 0;
}
You can make main file and try it see if its working for you .
Thanks
Change your code to the following and then report your results:
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
{
FILE* pfFile;
if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
{
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
if ((buffer = (char*) malloc (lSize)) == NULL)
return false;
// copy the file into the buffer:
result = fread (buffer,(size_t)lSize,1,pfFile);
fclose(pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
{
if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
{
size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
printf ("elements written <%d>\n", f);
if (f == 0)
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
}
}
}
}
return 0;
}
[edit]
for other posters, to show the usage/results of fwrite - what is the output of the following?
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = fopen ("f.kdt", "w+");
printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));
fclose (fp);
}
[/edit]
sizeof(buffer) is the size of the pointer, i.e. 4 and not the number of items in the buffer
If buffer is an array then sizeof(buffer) would potentially work as it returns the number of bytes in the array.
The third parameter to fwrite is sizeof(buffer) which is 4 bytes (a pointer). You need to pass in the number of bytes to write instead (lSize).
Update: It also looks like you're missing the flag indicating the file should be Read/Write: _O_RDWR
This is working for me...
std::string szdes = "C:\\temp\\test_des.txt";
FILE* pDesfFile;
int iFileId2;
err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, lSize, pDesfFile );
fclose (pDesfFile);
Since I can't find info about _sopen, I can only look at man open. It reports:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Your call _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE); doesn't match either one of those, you seem to have flags and 'something' and modes / what is SH_DENY?
What is the result of man _sopen?
Finally, shouldn't you close the file descriptor from _sopen after you fclose the file pointer?
Your final lines should look like this, btw :
if (iFileId2 >= 0)
{
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
fclose (pDesfFile);
}
Since you currently write the file regardless of whether or not the fdopen after the O_CREAT succeeded. You also do the same thing at the top, you process the read (and the write) regardless of the success of the fdopen of the RDONLY file :(
You are using a mixture of C and C++. That is confusing.
The sizeof operator does not do what you expect it to do.
Looks like #PJL and #jschroedl found the real problem, but also in general:
Documentation for fwrite states:
fwrite returns the number of full items actually written, which may be less than count if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
So if the return value is less than the count passed, use ferror to find out what happened.
The ferror routine (implemented both as a function and as a macro) tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.