C++ Parse Binary plist

2020-07-22 18:15发布

问题:

I am writing a program in c++ that will need to parse binary plists. XML parsing is not a problem, so I was thinking I could convert the binary plist to XML and then parse that. Is there a way to do this natively in c++? I know that apple's plutil has this capability but executing that from within the program seems like bad practice.

I am running the latest version of OS X (10.9)

回答1:

Assuming you want to do this on an apple platform You can use CFPropertyListCreateFromStream, CFPropertyListCreateWithData or CFPropertyListCreateWithStream, which are part of the CoreFoundation framework:
All of these functions have the following argument:

format: A constant that specifies the format of the property list. See Property List Formats for possible values.

CFPropertyListCreateFromStream also has the following argument:

stream: The stream whose data contains the content. The stream must be opened and configured—this function simply reads bytes from the stream. The stream may contain any supported property list type (see Property List Formats).

The CFProperty constants definition defines the following:

enum CFPropertyListFormat {
    kCFPropertyListOpenStepFormat = 1,
    kCFPropertyListXMLFormat_v1_0 = 100,
    kCFPropertyListBinaryFormat_v1_0 = 200
};
typedef enum CFPropertyListFormat CFPropertyListFormat;

This tends to indicate that the methods mentioned above can actually read binary plists.
Binary plist implementation details have also been open-sourced by Apple here.

Apple has some further sample code, the skinny of which is:

CFDataRef resourceData;
SInt32 errorCode;
Boolean status = CFURLCreateDataAndPropertiesFromResource(
           kCFAllocatorDefault, fileURL, &resourceData,
           NULL, NULL, &errorCode);

if (!status) {
    // Handle the error
}
// Reconstitute the dictionary using the XML data
CFErrorRef myError;
CFPropertyListRef propertyList = CFPropertyListCreateWithData(
                      kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, NULL, &myError);

// Handle any errors
CFRelease(resourceData);
CFRelease(myError);