I am working on a project in C++ with Eclipse Helios, QT 4.6.1 integration plugin and boost 1.52 libraries. I'd like to extract some information to work with from a xml file and I'm currently doing so by calling boost function const read_xml(std::string &, Ptree &, int = 0, const std::locale & = std::locale()).
The point is that I'd like to avoid final users to access that xml resource from the release folder and I have no idea of how to do it. Is there any (easy) way I could possibly treat that xml content from inside the executable in order to load it into memory and carry on with the rest of the process as I'm already doing with the xml file being treated as a project resource? Any tips would me more than appreciated.
Thanks in advance.
If you want to prevent the users of your program from modifying the XML file, you should use resources, to compile the file inside the executable.
If you are already using Qt, then by all means have a look at qrc in Qt 4.6. Qt provides a nice system independent way of embedding resource files into the executable. If your project is not already using Qt, then you probably don't want to add it just for that.
If you want a Windows-specific resource file, you can have a look at .rc files documentation. To check what was inside compiled resource files, I used ResEdit in the past and found it really useful. You can even create resource files with it.
If you are targeting Mac OS, you probably want to have a look at bundles, which are sort of a directory where you can put your resources. If you sign your application you can prevent the user to modify any file in the bundle (I'm not sure signing it is required though, I don't have much experience on Mac OS development).
And if you are targeting Linux or similar, you can try doing this trick which seems to work quite well.
All these methods aim to only embed your XML file into your executable, so that your users cannot easily modify it (well, in theory it is still possible but Muggles won't be able to do so). Reading the file may depend on the solution you choose. I personally dislike the Windows resource system and use it only when I really have to, avoiding the Win32 API like plague. If you choose to use Qt, it is quite easy to read the file, and you can do it with boost if you want to. Instead of reading the file at "resources/config.xml", you point to the resource file using ":/config.xml". Here would be the resource file:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>config.xml</file>
</qresource>
</RCC>
Then when you read it, I'm not sure if you have to use a Qt class to access it or not, but even if you do, you can open the file using QFile and call readAll, then use the result with boost:
QFile myConfigFile(":/config.xml");
if (!myConfigFile.open(QIODevice::ReadOnly | QIODevice::Text))
return;
read_xml(QString(myConfigFile.readAll()), [...]);
I haven't tested it but it should work with something like that.
The read_xml is overloaded. You are probably refering to this function:
read_xml(filename ... )
but there is also
read_xml(stream ...)
where stream is any std::istream object produced in any way. You could even have a hard-coded string in your source converted to a stream.
Thanks again for your tip Uflex. The point with my application was using QT but only for the GUI functionality, avoiding its use in the application controller underneath...
I've just checked your approach and it is mostly what I was looking for, except for the last line, since read_xml function accepts strings with the path to the xml file or stringstreams with the content of that xml. So, after combining your explanation with these two links:
How to feed Boost.PropertyTree with a string, not a file?
http://doc.qt.digia.com/4.6/resources.html
we are ready to go...
istringstream ss;
QFile file (QString::fromStdString(pathString));
if(file.open(QIODevice::ReadOnly | QIODevice::Text)){
ss.str(QString(file.readAll()).toStdString());
read_xml(ss, ...)
...
}
Related
Im trying to make (what I thought was a simple) extension for Game maker studio 2.
I am restricted to making a DLL app.
I am wondering is there any was to have a dll app open the file explorer have the user locate a file and then return said directory?
I fell like this is a sumb question but one I really need to know the answer too before slaving away coding for hours only to find its not possible.
You do not want to launch the explorer but to open a file dialog that allows the user to select a file.
Depending on the framework you use in your program the solutions may differ.
If you are using Qt framework you may use a QFileDialog for a platform independent mechanism.
If you are okay that it will only works on Windows then you may directly use the WinAPI functions GetOpenFileName or GetSaveFileName (that is a lot easier than the Common Item Dialog that is suggested as replacement on their documentation pages)
On GameMaker terms, you want to use get_open_filename or get_open_filename_ext.
See Dialog Module (marketplace, github) for C++ implementation reference.
I'm new to vc++, i have created a resource file and i need to read the file from my vc++ code. Is there any api available to read rc files. can anyone help me.
Assuming we're talking about Windows development here, you generally don't operate on a raw textual .rc file - you compile it in with your executable code then load the compiled resources based on what you're loading, like LoadString or LoadImage or LoadMenu. You would also put your dialog templates in there. And there are also functions for finding resources generically and accessing them in a more raw form if you need.
im stucking with Writing to Text File in the Resource, i can read from
the specified file, but cant write, its says Stream is not writeable.
there is any way to fix it ? i do it for my program builder, thanks in advice!
You can not write the the application bundle, pick another location, perhaps the Documents directory on iOS or the Application Support directory in OSX.
On iOS the resource bundle is also signed, another reason writing to it is not allowed.
I want to make an application, but the application will be using icons (bitmaps) for some of the menu buttons and other stuff. I want to keep my application as one simple, single standalone exe file which means I will somehow have to embed all of the icons into the application (EXE on windows) so I can load the bitmaps without having any external files.
Does anyone know how I can do this?
Just some other info:
I'm using wxWidgets, currently with MSVC and I would prefer a method that works cross compiler/cross platform if possible.
Thanks in advance!
You could used the XPM format for your bitmaps, as it's easy to embed in your code (which of course is going to be in the exe, right where you want it;-). As the docs say,
All wxWidgets platforms support XPMs
for small bitmaps and icons. You may
include the XPM inline as below, since
it's C code, or you can load it at
run-time
(the "as below" being a #include directive) -- so, you would be perfectly cross-compiler and cross-platform by adopting this approach with the "include" option.
For more info about the XPM format, see here. It's easy to find converters to XPM from other popular formats, of course.
Windows does have resource files.You could use that. Alternatively you could write a small utility that will convert your binary icon into a C constant array
eg:
const unsigned int my_icon[] = {0x12345678, 0x87654321, .... };
This could easily be done in perl and you can then access the icon with the variable my_icon.
Cause Linux has no platform solution for this you will have to create your own system anyway. So i would recommand against platform specific ways to add resources on windows and macosx.
You can use reswrap which comes with the FOX GUI Toolkit is a simple tool to convert any binary file into c char literals. If you compile with msvc you will soon find that large files with lot of large strings are poison for the compiler. I added about 900 icons for my project and it killed the compiler.
I currently work with a solution where i simply copy a binary archive at the end of the executable. Every platform today can give you the executable path and neither ELF, EXE or Mach-O files care if additional data is added at the end of an executable file.
We use this technique in our projects:
Use optipng ./image.png to optimize your png file.
Convert your binary image data to a text using png2wx Perl script.
Embed your image into the source code this way:
{
wxMemoryInputStream sm("\211PNG\r\n\032\n\000\000....", 116);
m_bitmap = wxBitmap( wxImage(sm) );
}
Do not forget to add the support for the PNG format in your wxApp::OnInit() function:
wxImage::AddHandler(new wxPNGHandler);
Here is the link to original tutorial.
Hope this will help!
I have to develop an application which parses a log file and sends specific data to a server. It has to run on both Linux and Windows.
The problem appears when I want to test the log rolling system (which appends .1 to the name of the creates a new one with the same name). On Windows (haven't tested yet on Linux) I can't rename a file that I have opened with std::ifstream() (exclusive access?) even if I open it in "input mode" (ios::in).
Is there a cross-platform way to open file in a non-exclusive way?
Is there a way to open file in a non-exclusive way,
Yes, using Win32, passing the various FILE_SHARE_Xxxx flags to CreateFile.
is it cross platform?
No, it requires platform-specific code.
Due to annoying backwards compatibility concerns (DOS applications, being single-tasking, assume that nothing can delete a file out from under them, i.e. that they can fclose() and then fopen() without anything going amiss; Win16 preserved this assumption to make porting DOS applications easier, Win32 preserved this assumption to make porting Win16 applications easier, and it's awful), Windows defaults to opening files exclusively.
The underlying OS infrastructure supports deleting/renaming open files (although I believe it does have the restriction that memory-mapped files cannot be deleted, which I think isn't a restriction found on *nix), but the default opening semantics do not.
C++ has no notion of any of this; the C++ operating environment is much the same as the DOS operating environment--no other applications running concurrently, so no need to control file sharing.
It's not the reading operation that's requiring the exclusive mode, it's the rename, because this is essentially the same as moving the file to a new location.
I'm not sure but I don't think this can be done. Try copying the file instead, and later delete/replace the old file when it is no longer read.
Win32 filesystem semantics require that a file you rename not be open (in any mode) at the time you do the rename. You will need to close the file, rename it, and then create the new log file.
Unix filesystem semantics allow you to rename a file that's open because the filename is just a pointer to the inode.
If you are only reading from the file I know it can be done with windows api CreateFile. Just specify FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE as the input to dwShareMode.
Unfortunally this is not crossplatform. But there might be something similar for Linux.
See msdn for more info on CreateFile.
EDIT: Just a quick note about Greg Hewgill comment. I've just tested with the FILE_SHARE* stuff (too be 100% sure). And it is possible to both delete and rename files in windows if you open read only and specify the FILE_SHARE* parameters.
I'd make sure you don't keep files open. This leads to weird stuff if your app crashes for example.
What I'd do:
Abstract (reading / writing / rolling over to a new file) into one class, and arrange closing of the file when you want to roll over to a new one in that class. (this is the neatest way, and since you already have the roll-over code you're already halfway there.)
If you must have multiple read/write access points, need all features of fstreams and don't want to write that complete a wrapper then the only cross platform solution I can think of is to always close the file when you don't need it, and have the roll-over code try to acquire exclusive access to the file a few times when it needs to roll-over before giving up.