- 追加された行はこの色です。
- 削除された行はこの色です。
プロパティリスト(Property List)は永續化(シリアライズ)の爲の手段である。Windows ユーザでも iTunes ライブラリを展開したものは、ここを覗く人なら居るかも知れない。嚴密にはプログラミング言語ではないが、Cocoa ではあまりにも重要なので扱ふことにする。
*目次 [#n7a36dc7]
#contents
[[プログラミング言語/Objective-C]]
*永續化對稱クラス [#d1fee6bd]
-NSString
-NSNumber(シリアライザは int か float か bool かを區別する)
-NSDate
-NSData
-NSArray
-NSDictionary
以上の物とそのサブクラスが對稱となる。以外はプロパティリストとして保存できない。またコレクションクラス(配列と辭書)の場合は格納するオブジェクトもこの基準に沿はねばならない。
*Cocoa API [#g8b73d0e]
Cocoa では Foundation フレームワークに plist 專用のクラスやメソッドが用意されてゐる。NSPropertyListSerialization クラスである。
** NSPropertyListSerialization クラス [#a3380e1a]
次の三つのクラスメソッドが定義される。
### NSPropertyListSerialization Class: Tasks
# Serializing a Property List
+ dataFromPropertyList:format:errorDescription:
# Deserializing a Property List
+ propertyListFromData:mutabilityOption:format:errorDescription:
# Validating a Property List
+ propertyList:isValidForFormat:
NSData 形式でテキストを渡しオブジェクトを復元して返すのが propertyListFromData メソッドである。 propertyList メソッドは復元可能かを調べる爲に使用する。dataFromPropertyList はオブジェクトインスタンスを永續化したテキストを NSData に格納して返す。エンコードは XML ならば UTF-8 になる。
+ (id)propertyListFromData: (NSData *)data
mutabilityOption:(NSPropertyListMutabilityOptions)opt
format:(NSPropertyListFormat *)format
errorDescription:(NSString **)errorString
+ (BOOL)propertyList:(id)plist
isValidForFormat:(NSPropertyListFormat)format
+ (NSData *)dataFromPropertyList:(id)plist
format:(NSPropertyListFormat)format
errorDescription:(NSString **)errorString
引數はこのやうになる。NSPropertyListFormat と NSPropertyListMutabilityOptions は以下の定數をとる。
NSPropertyListMutabilityOptions:
NSPropertyListImmutable
NSPropertyListMutableContainers
NSPropertyListMutableContainersAndLeaves
NSPropertyListFormat:
NSPropertyListOpenStepFormat # ASCII Property List
NSPropertyListXMLFormat_v1_0 # XML Property List
NSPropertyListBinaryFormat_v1_0 # Binary Property List
NSPropertyListFormat は種類の指定であり、NSPropertyListFormat は復元方法である。NSPropertyListFormat を引數にとる propertyList メソッドはどの種類に適合するかを判斷する訣である。dataFromPropertyList は通知された種類に永續化を試み、propertyListFromData は通知された種類に解する。
propertyListFromData で指定する NSPropertyListMutabilityOptions は變更可能なオブジェクトとするか否かであり、通常は NSPropertyListImmutable である。NSPropertyListMutableContainers は變更可能なオブジェクトであるが、その内部構成までは變更可能ではないインスタンスとして返す。NSPropertyListMutableContainersAndLeaves は全てのインスタンスが變更可能なオブジェクトとなる。
** NSArray, NSDictionary, NSString クラス [#rba888e0]
これらには特別に次のメソッドが與へられてゐる。
### NSArray Class: Tasks
# Creating an Array
+ arrayWithContentsOfFile
+ arrayWithContentsOfURL
# Initializing an Array
- initWithContentsOfFile
- initWithContentsOfURL
# Creating a Description
- writeToFile
- writeToURL
### NSDictionary Class: Tasks
# Creating a Dictionary
+ dictionaryWithContentsOfFile
+ dictionaryWithContentsOfURL
# Initializing an NSDictionary Instance
- initWithContentsOfFile
- initWithContentsOfURL
# Storing Dictionaries
- writeToFile
- writeToURL
### NSString Class: Tasks
Converting String Contents Into a Property List
– propertyList
– propertyListFromStringsFileFormat
NSArray 及び NSDictionary には復元と保存の兩樣のインスタンス乃至クラスメソッドがある。
NSData や NSString の場合 writeTo*** は中身を出力する爲のメソッドであり、NSString に關しては出力するファイルエンコーディングを指定して變換し保存する物だが、NSArray と NSDictionary は plist として保存する爲のメソッドになる。
NSString の propertyList は自身を Property List として解析しインスタンスを生成しそれを返し、propertyListFromStringsFileFormat は strings形式(cf. ASCII形式)として自身を解析して NSDictionary を返す。
* Apple Script での利用 [#k66cb63a]
Mac OS X v10.5 から讀み書きができるやうになります。
-http://www.apple.com/applescript/features/propertylists.html
* NeXTstep 形式プロパティリスト(OPENSTEP、ASCII形式) [#naf8ff10]
この形式の利點は人がみて讀みやすい所にある。ただし、古い形式であるため NSDate は NSString と、眞僞値は數値との區別がつかなくなる。
|クラス|値|記法|備考|h
|NSString|string|"string"|値が英數字及び「_」のみの時はダブルクオート無し。一部エスケープされる|
|NSNumber|YES(bool)|1|----|
|NSNumber|NO(bool)|0|----|
|NSNumber|20(int)|20|----|
|NSNumber|2.0(float)|2.0|----|
|NSDate|@referencetime|"YYYY-MM-DD HH:mm:ss ±XXXX"|ISO に基づくが、これは恐らく description の値|
|NSData|0xAD238FE8321.....|<10101101 00100011 0011.....>|バイナリは二進數に變換され、8bit=1byte ごとに半角スペースが入る|
|NSArray|[obj,obj,.....,obj]|(<obj>, <obj>, ...., <obj>)|<obj>の記法は各々のクラス依存|
|NSDictionary|[key=>obj,key=>obj]|{<key>=<obj>; <key>=<obj>; }|<obj>の記法は各々のクラス依存で、<key>はNSStringに同じ|
** NSString のエスケープ [#e96d156b]
Unicode のバイナリ値がそのまま出力される。やうは UTF-16 で出力する。「あ」は2ビットコードであり「U+3042」である。これは「\U3042」と出力される。改行コードは LF は「\n」に置換されるが、CR はそのままである。タブは「\t」に変換され、ダブルクオートもまた「\"」となる。バックスラッシュは重ねることになる。嚴密には、2ビット以上のUnicodeであるとバイナリ値へエスケープされるらしい。
|文字|エスケープ|備考|h
|a|a|値が英數字及び「_」のみの時はダブルクオートが無く、また左記に同じ。ASCIIの他は次のやうになる|
|あ|\U3042|Unicode は U+3042|
|タブ|\t|----|
|改行(LF)|\n|----|
|改行・復歸(CR)|(そのまま)|----|
|ダブルクオート(")|\"|----|
|バックスラッシュ(\)|\\|----|
** コレクションの改行 [#rb2f8855]
コレクションはその文字數を一列に並べた時に78バイトを超過すれば、アイテムごとに改行することになる。
{
"Application Version" = "8.0.1";
Features = 5;
"Library Persistent ID" = XXXXXXXXXXXXXXXX;
"Major Version" = 1;
"Minor Version" = 1;
"Music Folder" = "/Users/XXX/Music/iTunes/iTunes%20Music/";
Playlists = (
{
.....
},
.......
);
}
セミコロン(;)及びコロン(,)は必ず半角スペースを一つ後置する。これはダブルクオートで括らない場合への對處。コレクションの要素がこれらで區切られぬ場合、パーサはエラーを發する。なほ NSArray の最後の項目にはコロンが無いのが標準だが、うつかり附けてもきつちり認識される。
** コメント [#gb9fcd51]
コメントは次の三つの形式を許可する。
-//
-#
-/* */
お馴染みであらう。前者二項は改行、後者一項は「/*」で始まり「*/」で終はるまでがコメントと看做される。
** strings の爲の擴張 [#j89064cb]
strings は Localizable.strings など、NSBundle クラス等で取得しローカライズ辭書で使用される、UTF-16 でエンコーディングされた書類である。これのためにパーサは NSDictionary がルートである時に限り、ルート要素の NSDictionary には鍵括弧を必要としない。
よつて先程示した ASCII の plist は次のやうでも同樣に解釋されることになる。
"Application Version" = "8.0.1";
Features = 5;
"Library Persistent ID" = XXXXXXXXXXXXXXXX;
"Major Version" = 1;
"Minor Version" = 1;
"Music Folder" = "/Users/XXX/Music/iTunes/iTunes%20Music/";
Playlists = (
{
.....
}, /* これは註釋 */
.......
); # これも註釋
// これもさうである
Localized.strings では普通使はないけれど、他の NSArray などのコレクションをこれは要素として持つ事ができる。
* XML 形式プロパティリスト [#bcf884e8]
あまりこれといつた面白みがない。まづ手始めに DTD があるのでそれをみてみよう。/System/Library/DTDs/PropertyList-1.0.dtd にインストールされてゐる。http://www.apple.com/DTDs/PropertyList-1.0.dtd からも參照できる。
** Property List - Document Type Definition(plist DTD) [#ne413095]
<!ENTITY % plistObject "(array | data | date | dict | real | integer | string | true | false )" >
<!ELEMENT plist %plistObject;>
<!ATTLIST plist version CDATA "1.0" >
<!-- Collections -->
<!ELEMENT array (%plistObject;)*>
<!ELEMENT dict (key, %plistObject;)*>
<!ELEMENT key (#PCDATA)>
<!--- Primitive types -->
<!ELEMENT string (#PCDATA)>
<!ELEMENT data (#PCDATA)> <!-- Contents interpreted as Base-64 encoded -->
<!ELEMENT date (#PCDATA)> <!-- Contents should conform to a subset of ISO 8601
(in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'. Smaller units may be omitted with a loss of precision) -->
<!-- Numerical primitives -->
<!ELEMENT true EMPTY> <!-- Boolean constant true -->
<!ELEMENT false EMPTY> <!-- Boolean constant false -->
<!ELEMENT real (#PCDATA)> <!-- Contents should represent a floating point number matching
("+" | "-")? d+ ("."d*)? ("E" ("+" | "-") d+)? where d is a digit 0-9. -->
<!ELEMENT integer (#PCDATA)> <!-- Contents should represent a (possibly signed) integer number in base 10 -->
この DTD の素晴らしい點はこれをみれば Foundation の六つのクラスに必要なことと役割がある程度わかることである。
|エレメント|對應クラス|値|屬性|備考|
|plist|----|エンティティ plistObject を一つ|version|屬性は version="1.0" のみ許容|
|array|NSArray|エンティティ plistObject を0個以上|----|----|
|dict|NSArray|エレメント key とその次にエンティティ plistObject 、この組を0個以上|----|----|
|key|----|文字列|----|強いて言へば對應クラスは NSString|
|string|NSString|文字列|----|----|
|data|NSData|文字列|----|ただし書きには Base64 encode濟 であるとある|
|date|NSDate|文字列|----|ISO 8601 に基づく|
|true|NSNumber|----|----|値を取てはならない|
|false|NSNumber|----|----|値を取てはならない|
|real|NSNumber|文字列|----|ただし書き正規表現に從ふ文字列|
|integer|NSNumber|文字列|----|10進數のみ|
エンティティ plistObject は plist タグと key タグを除く全てになる。普通はしない DTD を定義したのは可視性の向上などにあると思はれる。この單純な(けれど冗長な)コーディングによつて、プログラマは xml を開いてみただけで何がシリアライズされてゐるのか把握することができるのである。
** NSData の改行 [#aea25014]
NSData のバイナリデータを Base64 でシリアライズするといふことは、それなりに厖大な長さになることが容易に想像できるかと思ふ。68文字(68バイト)で折疊むのが標準の模樣
** コメント [#b53079ff]
ASCII 形式ほどに編輯頻度は高くない。XML 形式のコメントが當然使へる。
** 實際のファイル [#ec96dfb8]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Application Version</key><string>8.0.1</string>
<key>Library Persistent ID</key><string>XXXXXXXXXXXXXXXX</string>
<key>Major Version</key><integer>1</integer>
<key>Minor Version</key><integer>1</integer>
<key>Music Folder</key><string>/Users/XXX/Music/iTunes/iTunes%20Music/</string>
<key>Playlists</key>
<array>
<dict>
........
</dict>
<dict>
.
.
</dict>
</array>
</dict>
</plist>
ASCII の Property List と同じ内容とした。dict、array はこのやうに改行することが多いが、data も68文字を越えて改行するとこのやうになる。
<array>
<data>
AQEAAw................
...
...
AAAAAAAAAAAA==
<data>
<array>
* バイナリ形式 [#i8a4edec]
一部調査中。「bplist00」で始まるバイナリファイル。パフォーマンス向上の爲に考案された。
追記:opensource.apple で公開されてる CF(CoreFoundation) Projectに CFBinaryPList.c といふファイルを發見。なんでもつと早く Carbon を思ひ出さなかつたんだらう・・・。
>
// CFBinaryPList.c
/*
HEADER
magic number ("bplist")
file format version
OBJECT TABLE
variable-sized objects
Object Formats (marker byte followed by additional info in some cases)
null 0000 0000
bool 0000 1000 // false
bool 0000 1001 // true
fill 0000 1111 // fill byte
int 0001 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
real 0010 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
date 0011 0011 ... // 8 byte float follows, big-endian bytes
data 0100 nnnn [int] ... // nnnn is number of bytes unless 1111 then int count follows, followed by bytes
string 0101 nnnn [int] ... // ASCII string, nnnn is # of chars, else 1111 then int count, then bytes
string 0110 nnnn [int] ... // Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte uint16_t
0111 xxxx // unused
uid 1000 nnnn ... // nnnn+1 is # of bytes
1001 xxxx // unused
array 1010 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
1011 xxxx // unused
set 1100 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
dict 1101 nnnn [int] keyref* objref* // nnnn is count, unless '1111', then int count follows
1110 xxxx // unused
1111 xxxx // unused
OFFSET TABLE
list of ints, byte size of which is given in trailer
-- these are the byte offsets into the file
-- number of these is in the trailer
TRAILER
byte size of offset ints in offset table
byte size of object refs in arrays and dicts
number of offsets in offset table (also is number of objects)
element # in offset table which is top level object
offset table offset
*/
**解説 [#l76115e5]
書き出すと長くなりさうだし、PropertyList Editor で書き出したファイルと上の註釋とを照らし合はせてほしい。
** コメント [#f9663e16]
そんなものはない。素人に編輯はできない。