Thursday, August 11, 2022

#1 2022-08-06 08:56:32 am

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2443

Writing the Record to plist file, then read it back

Hello,

I can write the record {aString:"Hello,word!", anInteger:1, aReal:3.14} to the plist file this  way:

Applescript:


{aString:"Hello,word!", anInteger:1, aReal:3.14} -- my test record

do shell script "defaults write my.domain myRecord -dict 'aString' 'Hello,word!' 'anInteger' '1' 'aReal' '3.14'"

My request for help is: how can I get my record back to my Apple-script, effectively?

Here is my attempt, which returns structured text instead of the record:

Applescript:

do shell script "defaults read my.domain myRecord"

the result is following:

"{
    aReal = \"3.14\";
    aString = \"Hello,word!\";
    anInteger = 1;
}"


Note that the order of entries is different when reading and writing!!!

Also, following gives to me the type (dictionary in this case) of myRecord in the plist file:

Applescript:


do shell script "defaults read-type my.domain myRecord"
--> "Type is dictionary"

Last edited by KniazidisR (2022-08-06 09:14:42 am)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#2 2022-08-06 09:22:10 am

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2443

Re: Writing the Record to plist file, then read it back

I got it! (with help from user @CK in the previous topic) smile

Applescript:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set resultString to (do shell script "defaults read my.domain myRecord")

my (NSString's stringWithString:resultString)'s propertyList() as record

Now, I have other problem: I can indicate the Type of every Value when writing to plist file, but the snippet above returns all Values as string!!!

Applescript:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

-- write
do shell script "defaults write my.domain myRecord -dict 'aString' -string 'Hello,word!' 'anInteger' -integer '1' 'aReal' -float '3.14'"
delay 1

-- read back
set resultString to (do shell script "defaults read my.domain myRecord")

my (NSString's stringWithString:resultString)'s propertyList() as record
--> {aReal:"3.14", aString:"Hello,word!", anInteger:"1"}

Is this my flaw or a flaw in AppeScriptObjC bridging? In any case, how to fix it, if possible?

Last edited by KniazidisR (2022-08-06 09:48:53 am)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#3 2022-08-06 10:02:53 am

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11771
Website

Re: Writing the Record to plist file, then read it back

KniazidisR wrote:


Now, I have other problem: I can indicate the Type of every Value when writing to plist file, but the snippet above returns all Values as string!!!



The values are string because you write all values as string (which is the default).

To write specific types you have to add flags like -int and -float

Applescript:

do shell script "defaults write my.domain myRecord -dict 'aString' 'Hello,word!' 'anInteger' -int '1' 'aReal' -float -'3.14'"

An alternative to read the data is

Applescript:

set plist to do shell script "defaults read my.domain myRecord"
set plistData to my ((NSString's stringWithString:plist)'s dataUsingEncoding:4)
set theRecord to (current application's NSPropertyListSerialization's propertyListWithData:plistData options:0 format:(my NSPropertyListOpenStepFormat) |error|:(missing value)) as record

Edit:

I noticed that in both cases the values are still string when reading back the data even without coercing to record. I regard this as a bridging issue

Second edit:

This reads the data correctly

Applescript:

set plistPath to POSIX path of (path to library folder from user domain) & "Preferences/my.domain.plist"
set plistData to my (NSData's dataWithContentsOfFile:plistPath)
set plist to (my (NSPropertyListSerialization's propertyListWithData:plistData options:0 format:(my NSPropertyListXMLFormat_v1_0) |error|:(missing value)))
set theRecord to (plist's objectForKey:"myRecord") as record

Last edited by StefanK (2022-08-06 11:46:59 am)


regards

Stefan

Offline

 

#4 2022-08-06 12:32:50 pm

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2443

Re: Writing the Record to plist file, then read it back

StefanK wrote:

The values are string because you write all values as string (which is the default).

To write specific types you have to add flags like -int and -float


No, I am writing correctly, and my entry matches yours (as I checked in BBEdit), you are just using the shortened form of option names.

StefanK wrote:


This reads the data correctly

Applescript:

set plistPath to POSIX path of (path to library folder from user domain) & "Preferences/my.domain.plist"
set plistData to my (NSData's dataWithContentsOfFile:plistPath)
set plist to (my (NSPropertyListSerialization's propertyListWithData:plistData options:0 format:(my NSPropertyListXMLFormat_v1_0) |error|:(missing value)))
set theRecord to (plist's objectForKey:"myRecord") as record



Excellent! Thanks for the help, it works.

Now it remains to understand only one thing: how to force defaults command not to add garbage from RAM to the tail of a real number when converted to a float. smile


Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

-- write
do shell script "defaults write my.domain myRecord -dict 'aString' -string 'Hello,word!' 'anInteger' -integer '1' 'aReal' -float '3.14'"
delay 1

-- read back
set plistPath to POSIX path of (path to library folder from user domain) & "Preferences/my.domain.plist"
set plistData to my (NSData's dataWithContentsOfFile:plistPath)
set plist to (my (NSPropertyListSerialization's propertyListWithData:plistData options:0 format:(my NSPropertyListXMLFormat_v1_0) |error|:(missing value)))
set theRecord to (plist's objectForKey:"myRecord") as record

--> {aString:"Hello,word!", aReal:3.140000104904, anInteger:1}

Last edited by KniazidisR (2022-08-06 12:41:26 pm)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#5 2022-08-06 12:50:20 pm

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11771
Website

Re: Writing the Record to plist file, then read it back

This is the normal imprecision of floating point numbers.

Please read Is floating point math broken? on Stackoverflow


regards

Stefan

Offline

 

#6 2022-08-06 11:28:43 pm

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2443

Re: Writing the Record to plist file, then read it back

It's annoying.

Because this means: you have to write a real in text form, then after reading the value, convert it back to a real, and for the correct reverse conversion on remote computers, you will have to define a local setting for the decimal separator.

Last edited by KniazidisR (2022-08-06 11:29:47 pm)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)