Reading a text file

I don’t know how to make some kind of preferences file that my script can read each time it runs, but I do know how to write to a text file. What I need now is to be able to read the last few characters of a text file and take different actions based on them. Anyone know how?

Sure, but be a bit more specific about the problem - you know how to read and write a file - what don’t you know?
Have you read “The Ins & Outs of File Read/Write” by Nigel Garvey?

Hi,

if you only want to read a file, create one in TextEdit with your data and save it as plain text.
Then you can read it with:

read file "path:to:the:file"

to get a list of e.g. all paragraphs, you can use a text delimiter

read file "path:to:the:file" using delimiter ASCII character 10

.

For handling preferences you can also use script objects

Thanks, this is perfect. I’m working up to reading through that sourcebook article, just starting it makes my head spin! What I’m trying to set up is a txt file that I can search for example "ChckbxA - " and then use the next characters to change my app. Anyway, happy scripting all!

Something like this:


set AppleScript's text item delimiters to ""
-- set up a file
set myText to "This file contains the word ChckbxA = false, and a bunch of stuff following it."

set f to open for access ((path to desktop folder as text) & "newFile.txt") with write permission
try
	set eof of f to 0 -- erases and starts at beginning
	write myText to f
	close access f
on error
	close access f
end try

-- Now read it
set T to read alias ((path to desktop folder as text) & "newFile.txt")
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "ChckbxA "
set P to text items of T
if (count P) = 2 then set P to text item 2 of P -- if count P > 2 then there is more than one ChckbxA
set AppleScript's text item delimiters to tid
set P to word 2 of P --> "false"

Thanks, that is exactly what I wanted!
How long have you been scripting, you seem to know everything.

Are you going to be using this method in an applescript studio app? If so, you’re missing out on the built-in capabilities of your app called “user defaults” that are the preferred method of storing application state. Saving your preferences in a text file is considered a hack, and should only be done in the most unique of cases. User defaults is easy to use, is automatically configured for every different user, and is technology that is built right into the application framework. That means no mess for you, no added work for you, and reliability that you will not be able to guarantee with your custom method.

If you’re not using this in a ASStudio project, then I apologize for making assumptions. Actually, even if you’re just using this in a plain applescript application, you can still access the user defaults system through ‘do script’ calls to a custom plist file, which is probably just are reliable, if not more, than reading and writing to a text file.

Using a plist file via user defaults is DEFINITELY the way to go in an ASStudio app. You should be wary of creating your own preferences scheme using reading and writing to text files. Using user defaults, you can do in two to four lines of code what you may end up writing in dozens of custom lines of reading/writing/parsing routines. Just something to think seriously about if your developing an ASS app.
j

I wrote my first AppleScript in March of 2004 - you can learn a ton in a couple of years. I’ll never be Kai, Nigel, Jobu, Jacques, or a few others but I get by. So will you in no time. As Kai says: “It’s only easy when you know the answer”, but first you have to encounter all the problems and understand the solutions, as you’re doing.

I’ve never had a problem storing a single word as a plist key, but have never succeeded in storing a long string of text. How do you do that in plain vanilla 'do shell script defaults write …" AppleScript? I’ve tried various quoting schemes, using the -string switch, etc. but it always errors.

You can use long strings, even ones with spaces in the key or value, as long as you single-quote the values you’re passing to the shell script. I don’t ever use the “quoted form of” command, but instead manually code the single quotes into the string I’m sending. I’d advise using only basic characters, alphanumeric and shift-modified numbers. Any extended characters will be converted to plain text by AS before being sent to the shell script. Also make sure not to send any single-quotes in your key or value strings, or it will prematurely end your enclosed string and throw an error.

set theDefaultsDomain to "com.jobu.eminent" --> Should be a reverse domain string w/no spaces & no ".plist" extension
set theKey to "Mauris molestie libero ut dolor tincidunt." --> Can be a string with spaces, as long as the shell script single-quotes it
set theValue to "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer aliquet egestas elit. Aliquam erat volutpat. Aenean arcu leo, semper a, eleifend et, tempor nec, justo. Vivamus accumsan. Nulla volutpat tortor a libero. Morbi dictum suscipit lorem. Aliquam porta. Vestibulum eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Cras eu eros. Donec ac sapien auctor massa vulputate egestas. Suspendisse dignissim nibh a ipsum."

writePlistEntry(theDefaultsDomain, theKey, theValue) --> Write the key/value pair
return (readPlistEntry(theDefaultsDomain, theKey)) --> Read the key/value pair, if possible

(* Subroutines *)
to writePlistEntry(tmpDomain, tmpKey, tmpValue)
	try
		set theShellScript to ("defaults write " & tmpDomain & " '" & tmpKey & "' '" & tmpValue & "'") --> Note the single-quotes
		do shell script theShellScript
		return true
	end try
	return false
end writePlistEntry

to readPlistEntry(tmpDomain, tmpKey)
	try
		set theShellScript to ("defaults read " & tmpDomain & " '" & tmpKey & "'") --> Note the single-quotes
		return ((do shell script theShellScript) as string)
	end try
	return "Error Reading Plist"
end readPlistEntry

j

Thanks, Jobu. Two very handy handlers - I’ve stored them in my box of tricks.

Translated into VF3K’s problem (without as much checking as I would normally do), we get:


set theDefaultsDomain to "com.SomeName.someText" -- make up a new name here
set theKey to "TextVal.1" --> Can be a string with spaces, as long as the shell script single-quotes it
set theValue to "This file contains the word ChckbxA = false, and a bunch of stuff following it."
writePlistEntry(theDefaultsDomain, theKey, theValue) --> Write the key/value pair

set theAnswer to getWord((readPlistEntry(theDefaultsDomain, theKey))) --> false

to getWord(theText)
	set tid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "ChckbxA "
	set P to text items of theText
	if (count P) = 2 then set P to text item 2 of P -- if count P > 2 then there is more than one ChckbxA
	set AppleScript's text item delimiters to tid
	return word 2 of P --> "false"
end getWord

to writePlistEntry(tmpDomain, tmpKey, tmpValue)
	try
		set theShellScript to ("defaults write " & tmpDomain & " '" & tmpKey & "' '" & tmpValue & "'") --> Note the single-quotes
		do shell script theShellScript
		return true
	end try
	return false
end writePlistEntry

to readPlistEntry(tmpDomain, tmpKey)
	try
		set theShellScript to ("defaults read " & tmpDomain & " '" & tmpKey & "'") --> Note the single-quotes
		return ((do shell script theShellScript) as string)
	end try
	return "Error Reading Plist"
end readPlistEntry

Thanks! I’m going to use that in my startup app to see what my prefs are. Anyone interested in seeing my startup app? I’d love some advice on it.

Anyway, I worked on it some more, and although it isn’t a finished product here it is! (I know the experienced scripters will wince)

write_to_file("Startup Initiated")
set currentDate to the current date
set timeStarted to the time of the currentDate
-- Open all apps --
set allApps to {"Quicksilver", "*Mail", "*Stickies", "*MiniBatteryLogger", "Dashboard KickStart", "GrowlHelperApp", "iTunesHelper", "GrowlMenu", "LiteSwitch X", "Alarm Clock", "TapDex", "Picture Switcher", "GrowlTunes", "Ejector"}
repeat with anApp in allApps
	if "*" is in anApp then
		set HideApp to word 2 of anApp
		if "MiniBatteryLogger" is in HideApp then
			tell application "MiniBatteryLogger" to activate
			tell application "System Events"
				tell process "MiniBatteryLogger" to set frontmost to true
				click button "Dismiss" of sheet 1 of window "MiniBatteryLogger" of application process "MiniBatteryLogger"
				set visible of process "MiniBatteryLogger" to false
			end tell
		else
			tell application HideApp to activate
			tell application "System Events" to set visible of process HideApp to false
		end if
	else
		tell application anApp to activate
	end if
end repeat
write_to_file("All Apps Opened")
-- Set display brightness --
setBrightness(1)
write_to_file("Brightness set")
-- Set energy saver settings --
setSlpDim("0", "180")
write_to_file("Sleep and dim set")
-- Set Volume based on source
setVolumeifSource("3", "6.5")
write_to_file("Volume set")
-- Display the date and time in a note (Stickied) --
set OnTimeGottenSecs to get_on_time_seconds()
set OnTimeGotten to get_on_time()
if OnTimeGottenSecs ≥ (60 * 5) then
	growl_notification("Brushed", "System Notice", "Startup occurred at " & currentDate)
else
	growl_notification("Brushed", "System Notice", "Login occurred at " & currentDate)
	growl_notification("Brushed", "System Notice", "The computer has been active for " & OnTimeGotten)
end if
-- Set network connections (Airport/Ethernet) --
start airport
enable airport
-- Display IP Address --
try
	set myIP to word 25 of (do shell script "curl checkip.dyndns.org")
	write_to_file("My IP address is " & myIP)
	growl_notification("Brushed", "Internet Connection", "JL's Mac is using the IP " & return & myIP)
on error
	set myIP to "No active internet connection"
	write_to_file("No active internet connection")
	growl_notification("Brushed", "Internet Connection", "There is no active internet connection")
end try

-- Set screen lock ON --
try
	tell application "System Preferences"
		activate
		set current pane to pane "com.apple.preference.security"
		tell application "System Events"
			tell process "System Preferences"
				set frontmost to true
				set SecState to value of checkbox "Require password to wake this computer from sleep or screen saver" of window "Security"
				my write_to_file("State of comp security = " & SecState)
				if value of checkbox "Require password to wake this computer from sleep or screen saver" of window "Security" = 0 then
					click checkbox "Require password to wake this computer from sleep or screen saver" of window "Security"
				end if
			end tell
		end tell
		quit
	end tell
on error errorText1
	write_to_file("Error setting security Prefs - " & errorText1)
end try
-- Check for new mail and display dialog if so --
tell application "Mail"
	check for new mail
	-- Send an email if my IP isn't from home.
	if myIP ≠ "72.136.59.185" then
		set newMessage to make new outgoing message with properties {subject:"JL's Mac Update", content:"IP address has changed to : " & myIP}
		tell newMessage
			make new to recipient at end of to recipients with properties {name:"Jamie", address:"jamie.lee1@gmail.com"}
		end tell
		send newMessage
	end if
end tell
-- Log running processes
set currentDate1 to the current date
set timeStarted1 to the time of the currentDate1
set startupTimeRunning to timeStarted1 - timeStarted
growl_notification("Brushed", "System Notice", "Startup took " & startupTimeRunning & " seconds")
tell application "System Events" to set allAppsActive to the (name of every process)
set RunningApps to ""
repeat with anApp in allAppsActive
	set RunningApps to RunningApps & anApp & ", "
end repeat
write_to_file("Startup Sequence took " & startupTimeRunning & " seconds")
write_to_file("The running apps at startup are: " & RunningApps)
growl_notification("Bezel", "System Notice", "Startup is complete")
write_to_file("Startup Completed" & return & return)
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
--	-- Handlers/Subroutines --	--
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
on setSlpDim(sleep, dim)
	do shell script ("pmset sleep " & sleep) password ¬
		"wasps365(haply" with administrator privileges
	do shell script ("pmset dim " & dim) password ¬
		"wasps365(haply" with administrator privileges
end setSlpDim
on write_to_file(this_data)
	set currentDate to the current date
	set target_file to "JL's Mac:Users:JTL:Startup Log:"
	set this_data to (currentDate & " : " & this_data & return) as text
	try
		set the target_file to the target_file as text
		set the open_target_file to ¬
			open for access file target_file with write permission
		write this_data to the open_target_file starting at eof
		close access the open_target_file
		return true
	on error
		try
			close access file target_file
		end try
		return false
	end try
end write_to_file
on setBrightness(bValue)
	tell application "System Preferences"
		activate
		set current pane to pane "com.apple.preference.displays"
		tell application "System Events"
			tell process "System Preferences"
				set bValueB4 to value of slider 1 of group 2 of tab group 1 of window 1
				my write_to_file("The brightness value = " & bValueB4)
				if bValueB4 ≠ bValue then
					tell slider 1 of group 2 of tab group 1 of window 1 to set value to bValue
				end if
			end tell
		end tell
		quit
	end tell
end setBrightness
on setVolumeifSource(headphoneVolume, InternalVolume)
	tell application "System Preferences"
		activate
		reveal anchor "output" of pane id ¬
			"com.apple.preference.sound"
		tell application "System Events" to tell process "System Preferences" to set S to value of text field 1 of row 1 of table 1 of scroll area 1 of tab group 1 of window "Sound"
		quit
	end tell
	if S = "Internal Speakers" then tell application "Finder" to set volume InternalVolume
	if S = "Headphones" then tell application "Finder" to set volume headphoneVolume
end setVolumeifSource
(*on growl_registration(AllNotifications, AppToRegister)
	tell application "GrowlHelperApp"
		register as application AppToRegister ¬
			all notifications AllNotifications ¬
			default notifications AllNotifications ¬
			icon of application "Finder"
	end tell
end growl_registration*)
on growl_notification(_name, _title, _description)
	tell application "GrowlHelperApp"
		notify with name _name ¬
			title _title ¬
			description _description ¬
			application name "Login Application"
	end tell
end growl_notification
on get_on_time()
	set t to GetMilliSec
	set hh to t div (3600.0 * 1000.0)
	set t to t - hh * (3600.0 * 1000.0)
	set mm to t div (60.0 * 1000.0)
	set t to t - mm * (60.0 * 1000.0)
	set ss to t / 1000.0
	hh & ":" & mm & ":" & ss & " since boot" as string
end get_on_time
on get_on_time_seconds()
	set t to GetMilliSec
	set hh to t div (3600.0 * 1000.0)
	set t to t - hh * (3600.0 * 1000.0)
	set mm to t div (60.0 * 1000.0)
	set t to t - mm * (60.0 * 1000.0)
	set ss to t / 1000.0
	hh & ":" & mm & ":" & ss & " since boot" as string
	set totalSeconds to ((hh * 60 * 60) + (mm * 60) + (ss)) as integer
	return totalSeconds
end get_on_time_seconds

P.S. Some of this is from the forum, thanks to all of the AMAZING scripting minds out there.