2017-05-20 04:49:07 +01:00
|
|
|
# plist-cil - A C# library for working with property lists
|
|
|
|
|
|
|
|
|
|
[](httsp://travis-ci.org/claunia/plist-cil)
|
|
|
|
|
|
|
|
|
|
This library enables .NET (CLR) applications to handle property lists of various formats.
|
2017-05-20 00:58:28 +01:00
|
|
|
It is mostly based on [dd-plist for Java](https://github.com/3breadt/dd-plist).
|
2017-05-20 04:49:07 +01:00
|
|
|
And as it, this is licensed under the terms of the MIT license.
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
Property lists are files used to store user settings and serialized objects.
|
2025-08-07 22:31:12 +01:00
|
|
|
They originate from the NeXTSTEP programming environment and are now a basic part of thhe Cocoa framework (macOS and
|
|
|
|
|
iOS) as well as the GNUstep framework.
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
## Features
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
* Read / write property lists from / to files, streams or byte arrays
|
|
|
|
|
* Convert between property lists formats
|
|
|
|
|
* Property list contents are provided as objects from the NeXTSTEP environment (NSDictionary, NSArray, NSString, etc.)
|
|
|
|
|
* Serialize native .NET data structures to property list objects
|
|
|
|
|
* Deserialize from property list objects to native .NET data structures
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
## Supported formats
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
* Cocoa XML
|
|
|
|
|
* Cocoa Binary (v0)
|
|
|
|
|
* Cocoa / NeXTSTEP / GNUstep ASCII
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
## Requirements
|
2025-08-07 22:31:12 +01:00
|
|
|
|
2021-04-21 12:08:40 +02:00
|
|
|
plist-cil targets:
|
|
|
|
|
|
|
|
|
|
- .NET Framework 4.5,
|
|
|
|
|
- .NET Standard 2.0
|
|
|
|
|
- .NET Core 2.1
|
|
|
|
|
- .NET Core 3.1.
|
|
|
|
|
- .NET 5.0
|
|
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
This means it should be compatible with Mono, Xamarin.iOS, Xamarin.Mac, UWP, etc. If you find an incompatibility, please
|
|
|
|
|
create an issue.
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
## Download
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2015-02-25 18:17:30 +00:00
|
|
|
The latest releases can be downloaded [here](https://github.com/claunia/plist-cil/releases).
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
## NuGet support
|
2025-08-07 22:31:12 +01:00
|
|
|
|
|
|
|
|
You can download the NuGet package directly from the [release](https://github.com/claunia/plist-cil/releases) page or
|
|
|
|
|
from the [NuGet Gallery](https://www.nuget.org/) or from [here](https://www.nuget.org/packages/plist-cil/).
|
2015-02-20 01:11:13 +00:00
|
|
|
|
2017-05-20 04:49:07 +01:00
|
|
|
## Help
|
2025-08-07 22:31:12 +01:00
|
|
|
|
2015-02-20 01:11:13 +00:00
|
|
|
The API documentation is included in the download.
|
|
|
|
|
|
|
|
|
|
When you encounter a bug please report it by on the [issue tracker](https://github.com/claunia/plist-cil/issues).
|
2017-05-20 04:49:07 +01:00
|
|
|
|
|
|
|
|
## Usage examples
|
|
|
|
|
|
|
|
|
|
### Reading
|
|
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
Parsing can be done with the PropertyListParser class. You can feed the `PropertyListParser` with a `FileInfo`, a
|
|
|
|
|
`Stream` or a `byte` array.
|
|
|
|
|
The `Parse` method of the `PropertyListParser` will parse the input and give you a `NSObject` as result. Generally this
|
|
|
|
|
is a `NSDictionary` but it can also be a `NSArray`.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
|
|
|
|
_Note: Property lists created by `NSKeyedArchiver` are not yet supported._
|
|
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
You can then navigate the contents of the property lists using the various classes extending `NSObject`. These are
|
|
|
|
|
modeled in such a way as to closely resemble the respective Cocoa classes.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
You can also directly convert the contained `NSObject` objects into native .NET Objects with the `NSOBject.ToObject()`
|
|
|
|
|
method. Using this method you can avoid working with `NSObject` instances altogether.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
|
|
|
|
### Writing
|
|
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
You can create your own property list using the various constructors of the different `NSObject` classes. Or you can
|
|
|
|
|
wrap existing native .NET structures with the method `NSObject.Wrap(Object o)`. Just make sure that the root object of
|
|
|
|
|
the property list is either a `NSDictionary` (can be created from objects of the type `Dictionary<string, Object>`) or a
|
|
|
|
|
`NSArray` (can be created from object arrays).
|
2017-05-20 04:49:07 +01:00
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
For building a XML property list you can then call the `ToXml` method on the root object of your property list. It will
|
|
|
|
|
give you an UTF-8 `string` containing the property list in XML format.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
If you want to have the property list in binary format use the `BinaryPropertyListWriter` class. It can write the binary
|
|
|
|
|
property list directly to a file or to a `Stream`.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
When you directly want to save your property list to a file, you can also use the `SaveAsXml` or `SaveAsBinary` methods
|
|
|
|
|
of the `PropertyListParser` class.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
|
|
|
|
### Converting
|
|
|
|
|
|
2025-08-07 22:31:12 +01:00
|
|
|
For converting a file into another format there exist convenience methods in the `PropertyListParser` class:
|
|
|
|
|
`ConvertToXml`, `ConvertToBinary`, `ConvertToASCII` and `ConvertToGnuStepASCII`.
|
2017-05-20 04:49:07 +01:00
|
|
|
|
|
|
|
|
## Code snippets
|
|
|
|
|
|
|
|
|
|
### Reading
|
|
|
|
|
|
2020-08-12 15:20:02 +02:00
|
|
|
```csharp
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
FileInfo file = new FileInfo("Info.plist");
|
|
|
|
|
NSDictionary rootDict = (NSDictionary)PropertyListParser.Parse(file);
|
|
|
|
|
string name = rootDict.ObjectForKey("Name").ToString();
|
|
|
|
|
NSObject[] parameters = ((NSArray)rootDict.ObjectForKey("Parameters")).GetArray();
|
|
|
|
|
foreach(NSObject param in parameters)
|
2017-05-20 04:49:07 +01:00
|
|
|
{
|
2020-08-12 15:20:02 +02:00
|
|
|
if(param.GetType().Equals(typeof(NSNumber)))
|
2017-05-20 04:49:07 +01:00
|
|
|
{
|
2020-08-12 15:20:02 +02:00
|
|
|
NSNumber num = (NSNumber)param;
|
|
|
|
|
switch(num.GetNSNumberType())
|
2017-05-20 04:49:07 +01:00
|
|
|
{
|
2020-08-12 15:20:02 +02:00
|
|
|
case NSNumber.BOOLEAN:
|
2017-05-20 04:49:07 +01:00
|
|
|
{
|
2022-10-03 19:27:22 +02:00
|
|
|
bool boolean = num.ToBool();
|
2020-08-12 15:20:02 +02:00
|
|
|
// ...
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case NSNumber.INTEGER:
|
|
|
|
|
{
|
|
|
|
|
long l = num.ToLong();
|
|
|
|
|
// or int i = num.ToInt();
|
|
|
|
|
// ...
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case NSNumber.REAL:
|
|
|
|
|
{
|
|
|
|
|
double d = num.ToDouble();
|
|
|
|
|
// ...
|
|
|
|
|
break;
|
2017-05-20 04:49:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-12 15:20:02 +02:00
|
|
|
// else...
|
2017-05-20 04:49:07 +01:00
|
|
|
}
|
2020-08-12 15:20:02 +02:00
|
|
|
}
|
|
|
|
|
catch(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(ex.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
```
|
2017-05-20 04:49:07 +01:00
|
|
|
|
|
|
|
|
### Writing
|
|
|
|
|
|
2020-08-12 15:20:02 +02:00
|
|
|
```csharp
|
|
|
|
|
// Creating the root object
|
|
|
|
|
NSDictionary root = new NSDictionary();
|
|
|
|
|
|
|
|
|
|
// Creation of an array of length 2
|
|
|
|
|
NSArray people = new NSArray(2);
|
|
|
|
|
|
|
|
|
|
// Creation of the first object to be stored in the array
|
|
|
|
|
NSDictionary person1 = new NSDictionary();
|
|
|
|
|
// The NSDictionary will automatically wrap strings, numbers and dates in the respective NSObject subclasses
|
|
|
|
|
person1.Add("Name", "Peter"); // This will become a NSString
|
|
|
|
|
// Use the DateTime class
|
|
|
|
|
person1.Add("RegistrationDate", new DateTime(2011, 1, 13, 9, 28, 0)); // This will become a NSDate
|
|
|
|
|
person1.Add("Age", 23); // This will become a NSNumber
|
|
|
|
|
person1.Add("Photo", new NSData(new FileInfo("peter.jpg")));
|
|
|
|
|
|
|
|
|
|
// Creation of the second object to be stored in the array
|
|
|
|
|
NSDictionary person2 = new NSDictionary();
|
|
|
|
|
person2.Add("Name", "Lisa");
|
|
|
|
|
person2.Add("Age", 42);
|
|
|
|
|
person2.Add("RegistrationDate", new NSDate("2010-09-23T12:32:42Z"));
|
|
|
|
|
person2.Add("Photo", new NSData(new FileInfo("lisa.jpg")));
|
|
|
|
|
|
|
|
|
|
// Put the objects into the array
|
|
|
|
|
people.SetValue(0, person1);
|
|
|
|
|
people.SetValue(1, person2);
|
|
|
|
|
|
|
|
|
|
// Put the array into the property list
|
|
|
|
|
root.Add("People", people);
|
|
|
|
|
|
|
|
|
|
// Save the property list
|
|
|
|
|
PropertyListParser.SaveAsXml(root, new FileInfo("people.plist"));
|
|
|
|
|
```
|