I have been unable to open the file. The fb.is_Open() never returns true. Only when I hard code the data source in the fb.open() it works.
I've tried converting it to a string, char, and wstring with no effect.
What am I missing? The correct code would be fantastic but also and explanation.
Trying to open a file with the data source variable:
wchar_t dataSource[2048];
DWORD errNum = GetModuleFileName(NULL, dataSource, sizeof(dataSource)); //get current dir.
ifstream fb;
wcscat_s(dataSource, L".confg"); //adds ".config" to get full data Sournce
fb.open(dataSource, ios::in);
if (fb.is_open())
{
//get information
}
fb.close();
Here are some things Ive tried that have not worked:
wstring x = dataSource;
x.c_str()
char* cnvFileLoc = (char*)malloc(2048);
size_t count;
count = wcstombs_s(&count, cnvFileLoc, 2048, dataSource, 2048);
what does work is:
fb.open(X:\CPP.Lessons\PluralSight\PluralSight.Fundamentals\Debug\PluralSight.Fundamentals.exe.config, ios::in)
Your call to GetModuleFileName() is wrong. The last parameter is expressed in characters, not in bytes, and the return value tells how many characters were copied:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, 2048) > 0)
{
...
}
Or:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, sizeof(dataSource)/sizeof(dataSource[0])) > 0)
{
...
}
Or:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, _countof(dataSource)) > 0)
{
...
}
Or:
wchar_t dataSource[2048];
if (GetModuleFileName(NULL, dataSource, ARRAYSIZE(dataSource)) > 0)
{
...
}
That being said, you are appending .confg to the end of the full filename. So, if your application is named myapp.exe, you are trying to open myapp.exe.confg. Is that what you really want?
If yes, then make sure the .confg file actually exists, and that your app has permission to access it. CreateFile() would offer much more useful error info then ifstream does.
Otherwise, assuming the .confg file is at least in the same folder as your app, you would have to manually remove the filename portion from the buffer and then substitute in the correct filename. Have a look at PathRemoveFileSpec() and PathCombine() for that. Or, if the file is named myapp.confg, look at PathRenameExtension().
Update: I just noticed that your code is appending .confg, but your comment says .config instead:
//wcscat_s(dataSource, L".confg");
wcscat_s(dataSource, L".config");
You may have mistyped the file extension: L".confg" instead of L".config" as stated by the comment in your code.
Related
I had some doubts about fopen...
Can i perform the following?
fopen("%temp%" , "r");
or do i need to use windows specific functions?
No, you cannot do directly (unless you want to open file called %temp). There is a function ExpandEnvironmentStrings that does that:
char path[MAX_PATH];
ExpandEnvironmentStrings("%TEMP%\\tempfile", path, MAX_PATH);
fopen(path, "r");
You can do that manually -- in this case it can be more portable:
char path[MAX_PATH];
const char* temp = getenv("TEMP");
if(temp == NULL)
; // Return an error or try to guess user's Temp
// directory with GetUserProfileDirectory or similiar functions
snprintf(path, MAX_PATH - 1, "%s\\tempfile", temp);
fopen(path , "r");
But there is a cleaner option for your case -- tmpfile
On Windows you can use GetTempPath function that simply expands your %TEMP% env variable.
Note, that starting from C++17 you can use std::filesystem::temp_directory_path
Hey I'm having trouble with file IO. I am using some standard file pointer stuff but i keep getting this error: Unhandled exception at 0x58CBC465 (msvcr120_app.dll) in ChemicalWar.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Now from what I gathered I think it has something to do with not having permission to write to default location but I am unsure how to change the location.
here is the code I wrote so far that is giving me trouble:
FILE* ofile;
NametoBinary(_filename);
fopen_s(&ofile, (char*)folder->ToString(), "wb");
fwrite(&animhead, sizeof(Afhead), 1, ofile);
fwrite(binbuff.data(), sizeof(unsigned char), binbuff.size(), ofile);
fclose(ofile);
it breaks on the first fwrite call. Any help would be great. Thanks in advance.
So I figured out the solution so I will post it in case anyone else needs to know.
FILE* ofile = nullptr;
NametoBinary(_filename);
auto folder = Windows::Storage::ApplicationData::Current->RoamingFolder;
std::wstring ws(folder->Path->Data());
std::string full(ws.begin(), ws.end());
full += "\\";
full += _filename;
fopen_s(&ofile, full.c_str(), "wb");
if (nullptr == ofile) return false;
fwrite(&animhead, sizeof(Afhead), 1, ofile);
So the new windows apps have there own FileI0 system. This solution will save a file in a folder in the appdata folder.
I'm having trouble writing a short buffer into a wav file on my HD.
I followed a few tutorials, but they all give different ways of doing it.
Anyway, this is the way I implemented it but for some reason it doesn't work. When I try to print out the result of outfile, I get a 0, and nothing is written to disk.
Also, I tried different paths, sometimes with and sometimes without a file name.
UPDATE: When I change the path to only a file name (e.g. hello.wav and not ~/Documents/hello.wav), printing out the outfile returns a memory location such as 0x2194000.
void gilbertAnalysis::writeWAV(float * buffer, int bufferSize){
SF_INFO sfinfo ;
sfinfo.channels = 1;
sfinfo.samplerate = 44100;
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
const char* path = "~/Documents/hello.wav";
SNDFILE * outfile = sf_open(path, SFM_WRITE, &sfinfo);
sf_count_t count = sf_write_float(outfile, &buffer[0], bufferSize) ;
sf_write_sync(outfile);
sf_close(outfile);
}
From the libsndfile docs:
On success, the sf_open function returns a non-NULL pointer which should be passed as the first parameter to all subsequent libsndfile calls dealing with that audio file. On fail, the sf_open function returns a NULL pointer. An explanation of the error can obtained by passing NULL to sf_strerror.
If outfile is 0x2194000 and not null, then you probably opened the file correctly.
Try using sf_strerror() to see what error you had when you provided a full file path and not just the file name.
Tilde (~) in file names expands to home directory by shell. For library functions file path must be full, either absolute or relative.
Having trouble with the after effects sdk.
Basically I'm looping through all of the footage project items and trying to get the footage path from them. Here's the code I have inside of the loop.
AEGP_ItemType itemType = NULL;
ERR(suites.ItemSuite6()->AEGP_GetNextProjItem(projH, itemH, &itemH));
if (itemH == NULL) {
break;
}
ERR(suites.ItemSuite6()->AEGP_GetItemType(itemH, &itemType));
if (itemType == AEGP_ItemType_FOOTAGE) {
numFootage++;
AEGP_FootageH footageH;
ERR(suites.FootageSuite5()->AEGP_GetMainFootageFromItem(itemH, &footageH));
A_char newItemName[AEGP_MAX_ITEM_NAME_SIZE] = {""};
wchar_t footagePath[AEGP_MAX_PATH_SIZE];
ERR(suites.ItemSuite6()->AEGP_GetItemName(itemH, newItemName));
AEGP_MemHandle pathH = NULL;
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&footagePath)));
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
const std::string utf8_string = converter.to_bytes(footagePath);
std::ofstream tempFile;
tempFile.open ("C:\\temp\\log1.txt");
tempFile << utf8_string;
tempFile.close();
ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(pathH));
ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));
}
I'm getting the footagePath
I then convert the UTF-16 (wchar_t) pointer to a UTF-8 string
Then I write that UTF-8 string to a temp file and it always outputs the following.
펐㛻
Can I please have some guidance on this? Thanks!
I was able to figure out the answer.
http://forums.adobe.com/message/5112560#5112560
This is what was wrong.
It was because the executing code was in a loop and I wasn't allocating strings with the new operator.
This was the line that needed a new on it.
wchar_t footagePath[AEGP_MAX_PATH_SIZE];
Another piece of information that would have been useful to know is that not ALL footage items have paths.
If the don't have a path it will return empty string.
This is the code I ended up with.
if (itemType == AEGP_ItemType_FOOTAGE) {
A_char* newItemName = new A_char[AEGP_MAX_ITEM_NAME_SIZE];
ERR(suites.ItemSuite6()->AEGP_GetItemName(newItemH, newItemName));
AEGP_MemHandle nameH = NULL;
AEGP_FootageH footageH = NULL;
char* footagePathStr = new char[AEGP_MAX_PATH_SIZE];
ERR(suites.FootageSuite5()->AEGP_GetMainFootageFromItem(newItemH, &footageH));
if (footageH) {
suites.FootageSuite5()->AEGP_ GetFootagePath(footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &nameH);
if(nameH) {
tries++;
AEGP_MemSize size = 0;
A_UTF16Char *nameP = NULL;
suites.MemorySuite1()->AEGP_GetMemHandleSize(nameH, &size);
suites.MemorySuite1()->AEGP_LockMemHandle(nameH, (void **)&nameP);
std::wstring test = L"HELLO";
std::string output;
int len = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)nameP, -1, NULL, 0, NULL, NULL);
if (len > 1) {
footagePathStr = new char[len];
int len2 = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)nameP, -1, footagePathStr, len, NULL, NULL);
ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(nameH));
suites.MemorySuite1()->AEGP_FreeMemHandle(nameH);
}
}
}
}
You've already had the data as smarter std::wstring, why did you convert it to byte array and then force it as simple std::string? In general, you should avoid converting strings via byte arrays. My knowledge on C++ STDLIB is a few years off now, but the problem may be in that the std::string class may simply still not have any UTF8 support.
Do you really need to store it as utf8? If it is just for logging, try using ofwstream (the wide one), remove the conversion and the 'string' completely, and just write the 'wstring' directly to the stream instead.
Also, it is completely possible that everything went correctly, and it is just your FILE VIEWER that goes rabid. Examine your log file with hexeditor and check if the beginning of the file contains the Unicode format markers like 0xFFFE etc:
if it has some, and you wrote data in not-identical encoding as the markers indicate, then that's the problem
if it has none, then try adding correct markers. Maybe your file-viewer simply did not notice it is unicode-of-that-type and misread the file. Unicode markers help the readers to decode data properly.
I'm pretty close to losing my head here ;)
I'm developing a service that uses gsoap. I would like to return a mime response.
I have everything working, but when reading binary files, all kind of files like jpeg, pdf, etc... contains the \0 char several times over the data (if opened with notepad can see a lot of NUL).
So any code for reading a raw file fails miserably once it finds the end-of-file char. I have tried to replace the \0 but the file becomes incorrect to display.
I have also tried several methods including the example that comes with gsoap.
So resuming,
fstream generic code doesn't work.
for (i = 0; i < MAX_FILE_SIZE; i++)
{ if ((c = fgetc(fd)) == EOF)
break;
image.__ptr[i] = c;
}
doesn't work also
QFile::ReadAll works but when converting QString to char* the array is trimmed in the first NUL.
So, which is the best aproach to read an entire binary file? Its crazy how sometimes C++ at the basic.
Thanks in advance.
I have tried this as retnick suggested below
UrlToPdf urlToPdf;
urlToPdf.getUrl(&input, &result);
QByteArray raw = urlToPdf.getPdf(QString(result.data.c_str()));
int size = raw.toBase64().size();
char* arraydata = new char[size];
strcpy(arraydata, raw.toBase64().data());
soap_set_mime(this, "MIME_boundary", NULL);
if(soap_set_mime_attachment(this, arraydata, size, SOAP_MIME_BASE64, "application/pdf", NULL, NULL, NULL))
{
soap_clr_mime(this);
soapMessage = this->error;
}
but no luck... the mime response is bigger than the actual file...
David G Ortega
to read binary files use fread()
Once you read it treat it as an array of bytes not as a string. No string functions allowed.
EDIT: The gSOAP documentation section 14.1 explains how to send MIME attachments. I only refer to the relevant function (please read it all).
int soap_set_mime_attachment(struct soap *soap, char *buf_ptr, size_t buf_size,
enum soap_mime_encoding encoding,
const char *type, const char *id,
const char *location, const char *description);
char *buf_ptr is your buffer.
size_t buf_size is the length of your buffer.
So just do your QFile::ReadAll.
this gives you back a QByteArray. The QByteArray has the method
QByteArray QByteArray::toBase64 () const
this will return a
QByteArray base64image = QByteArray::toBase64(rawImage);
so now just do
soap_set_mime(soap, "MIME_boundary", "<boundary.xml#just-testing.com>");
/* add a base64 encoded image (base64image points to base64 data) */
soap_set_mime_attachment(soap,
base64image.data(), base64image.size(),
SOAP_MIME_BASE64, "image/jpeg",
"<boundary.jpeg#just-testing.com>", NULL, NULL);
I have not tested this but should be close to finished.
QFile::ReadAll works but when converting QString to char* the array is trimmed in the first NUL.
Are you sure it's actually trimmed or you just can't print/view the array in the debugger [since C-style strings are 0 terminated]?
If the QString itself is not enough for your needs you may want to convert it to a std::vector or similar using the range constructor or range assign, you'll have lots less grief towards the how much data the container holds.
EDIT:
Here's some sample code for fstream reading from a binary file:
std::ifstream image( <image_file_name>, std::ios_base::in | std::ios_base::binary );
std::istream_iterator< char > image_begin( image ), image_end;
std::vector< char > vctImage( image_begin, image_end );
The std::ios_base::binary is the most important part of the thing (similar to fopen/fread ["rb"] & probably QFile has something similar)
Also posting some sample code usually helps in getting the right answer.
HIH
I have the solution for this... As renick suggested I tried his idea but it failed without undestanding it so much... From a logical point of view recnick was right... bat the truth is that any king of string manipulation using QT QByteArray, std or mem is going to stop when findind the first \0 char, Qt QString can do it without problems but when converting it to c string (char*) the data will be again trimmed with the first \0
I found that using QDataStream::readRawData reads the file into a char* given the size to read. So thats how I accomplished the deal...
QFile file("test.pdf");
file.open(QIODevice::ReadOnly);
int size = file.size();
char* buffer = new char[size];
QDataStream stream(&file);
stream.readRawData(buffer, size);
soap_set_mime(this, "MIME_boundary", NULL);
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
{
soap_clr_mime(this);
soapMessage = this->error;
}
Note that in the line
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
I'm still using the size var instead of doing sizeof(buffer) or any other aproach since this one is going to trimm again the data qhen finding the first \0...
Hope this helps...
David G Ortega