Hello,
while I can read without any problem the plists of several apps, when I try to read Xcode’s plist I get garbage. For instance:
dim f as FolderItem = GetOpenFolderItem("")
if f <> nil then
dim b as BinaryStream = BinaryStream.Open(f,false) //b.Position = 200
dim s as String = DefineEncoding(b.Read(b.Length), Encodings.utf8)
b = nil
end if
In the debugger, the first lines of s look like this:
bplist00?“a
e !”#$%&&’(#??????????^?_#a#c
I tried setting b.position to 3, 4 ,5 and so on, but I still get garbage.
Removing the encoding and changing lineEndings do not make things better.
Opening the file as textInputStream still results in garbage.
I removed BOM with Kem’s M_string utility, still garbage.
I tried opening the file as xml, but the file is not recognized as valid xml.
Yet, opening the file in TextWrangler, everything looks all right:
Plist files are normally stored in a compressed binary format (which is what you are seeing), there are programs such as Apples Plist Editor, XCode, TextWrangler(it seems) and UltraEdit, the can open them and translate to XML format
So PLIST basically have TWO acceptable formats it seems
You can direct the output of plutil to stdout by using a - as the output file
/usr/bin/plutil -convert xml1 -o -
or for JSON format
/usr/bin/plutil -convert json -o -
either way you can feed the result of the shell to create a JSONItem or XML object to work with. (I think JSON would be simpler to deal with than xml for plists as they’re all key-value based)
On further experimentation, I would avoid using the JSON functionality. It will choke on any plist with a Date field… there seem to be other (undocumented) things it doesn’t like so I would just stick to XML…
There’s 3 possible formats for a plist file, the current favorite by Apple is the binary format.
I never ever recommend using a third party or extra step involved in the process, unless you control that step. The reason being is that in the early days of OS X, I was using a third party object to handle plists. As the format migrated and the tool didn’t I was left having to spend the time learning how to do it properly, when I didn’t have the time.
Reading a dictionary based plist is easy.
declare function dictionaryWithContentsOfURL lib "Foundation" selector "dictionaryWithContentsOfURL:" ( classRef as Ptr, inURL as Ptr ) as Ptr
return dictionaryWithContentsOfURL( NSClassFromString( "NSDictionary" ), inURL )
Similar for creating a plist from a NSDictionary or NSArray.
declare function writeToURL lib "Foundation" selector "writeToURL:atomically:" ( ref as Ptr, urlRef as Ptr, atomically as boolean ) as Boolean
return writeToURL( NSObjectRef, inURL, atomically )
However, there are objects that the standard plist format doesn’t handle (I forget which), so it’s better to use “NSKeyedUnarchiver” and “NSKeyedArchiver”.
All of these functions require a good converter between Xojo and NS.
Since it’s not clear whether you read a prefs plist or maybe the info.plist, here’s little warning:
It’s not safe to read the plist file directly of any app’s preferences. If it’s some other plist that not’s in the Preferences folder, the above is okay. That’s because, since 10.8 (or something around that time) Apple started using a background process called “cdprefsd” that caches the app’s prefs. So, when an app changes its prefs, it won’t be immediately updated in the plist file.
To read those prefs properly, on all OSX versions, use the CFPreferences functions instead, supplying the the bundle ID of the app whose prefs you want to access.