När man utvecklar AIR appar så måste man kunna spara information från appen på något sätt. Det är inte alltid man kan förlita sig på internet-anslutning och server-side sparande. Eller så är det så enkelt att man vill inte spara data över internet.
Därför kommer här en liten tutorial som visar hur du kan spara data lokalt på användarens dator, oavsett om der är en Win, Mac eller Linux.
I den här tutorialn så kommer jag visa dig hur du sparar data lokalt på användarens dator.
Först, de 3 bibliotek som är viktiga för hantering av lokala filer är följande:
import flash.filesystem.File; // Hantera filer, sökvägar mm.
import flash.filesystem.FileMode; // Hantera olika lägen av filer, nästan som FTP, WRITE och READ
import flash.filesystem.FileStream; // Hantera läsandet och skrivandet från och till en fil
Kom ihåg: Om man samtidigt tänker på prestandan så är det bra att åter använda en redan befintlig funktion
XML struktur är väldigt lätt-hanterad i As3 så därför gör vi ett exempel på det.
Steg 1:Importera in behövande bibliotek i ditt flash projekt och skapa ett XML struktur som ska sparas.
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
var minXML:XML = <rooten> <sitenamn>FlashGuru</sitenamn><siteurl>www.flashguru.se</siteurl></rooten>;
Steg 2:Vi skapar ett fil-objekt och hänvisar var filen vi skapar, ska lagras...
// Sökvägen till filen
var filMapp:File = File.applicationStorageDirectory;
Den returnerar följande på motsvarande platformar:
MAC: /Users/(
Användare)/Library/Preferences/(
Appnamn)/Local Store/
WIN: (
Användare)/Application Data/(
Appnamn)/Local Store/

Genom fil-objektet kan vi även bestämma vad filen ska heta, exempelvis minfil.xml
// Sökvägen till filen
var filMapp:File = File.applicationStorageDirectory;
var fil:File = filMapp.resolvePath("minfil.xml");
Notera: variablen fil, innehåller nu alltid fulla sökvägen + filnamnet
Exempel:
- MAC: /Users/(Användare)/Library/Preferences/(Appnamn)/Local Store/minfil.xml
- WIN: (Användare)/Application Data/(Appnamn)/Local Store/minfil.xml
Vi har nu bestämt i AS3 var filen ska ligga och vad den ska heta.
Nästa steg är att skapa 2 funktioner, 1 för att spara data, och en för att läsa.
Steg 3:För att skriva till filen använder vi FileStream-objektet som behöver 2 saker av oss:
- Fil-objekt (för att veta var filen ska sparas och vad den ska heta)
- Data som ska sparas i den filen
function writeToFile(_file:File, _data:XML):void{
//Konventera data till en String
var dataString:String = _data.toXMLString();
// skapa FileStream
var fs:FileStream = new FileStream();
// Öppna filen och ge den rättigheter / FileMode
fs.open(_file, FileMode.WRITE);
// Skriv data i filen
fs.writeUTFBytes(dataString);
// Stäng filen
fs.close();
}
- var dataString:String = _data.toXMLString(); - Först konventerar vi _data (som är XML) till en enda String. Det på grund av att writeUTFBytes hanterar inte data som XML-objekt, utan den kan hantera data som String-objekt
- var fs:FileStream = new FileStream(); - Sedan skapar vi FileStream som tillåter oss att hantera filen.
- fs.open(_file, FileMode.WRITE); - Öppna filen som passerades in i funktionen och ge den filen ett FileMode, i vårt fall WRITE
- fs.writeUTFBytes(dataString); - När WRITE-mode är satt så skriver AIR till filen
- fs.close() - och till slut när den är klar, så stängs filen
Steg 4:Nästa funktion som vi skapar är för att läsa från filen. Den är nästan identisk till writeToFile() funktionen, dock med skillnad att vi behöver bara passera till den filen som vi vill läsa ifrån.
function readFromFile(_file:File):void{
if(_file.exists){
// skapa FileStream
var fs:FileStream = new FileStream();
// Öppna filen och ge den rättigheter / FileMode
fs.open(_file, FileMode.READ);
// Skapa ett XML objekt som innehåller data som läses in
var filDataXML:XML = new XML(fs.readUTFBytes(fs.bytesAvailable));
// Stäng filen
fs.close();
trace(filDataXML);
}
}
- if(_file.exists){ - Kolla att filen existerar, annars får #3003 error (se nedan)
- var fs:FileStream = new FileStream(); - Skapar ett nytt FileStream
- fs.open(_file, FileMode.READ); - Öpnnar filen med FileMode ställd på läsning (READ)
- var filDataXML:XML = new XML(fs.readUTFBytes(fs.bytesAvailable)); - Skapar ett nytt XML-objekt av datan som läses in (Kom ihåg: Data som läses in är en String)
- fs.close(); - Till slut stänger filen
- trace(filDataXML); - kör trace för att se vad som lästes in
Error: Error #3003: File or directory does not exist. at flash.filesystem::FileStream/open() at Untitled_fla::MainTimeline/readFromFile()[Untitled_fla.MainTimeline::frame1:18] at Untitled_fla::MainTimeline/frame1()[Untitled_fla.MainTimeline::frame1:23] at runtime::ContentPlayer/loadInitialContent() at runtime::ContentPlayer/playRawContent() at runtime::ContentPlayer/playContent() at runtime::AppRunner/run() at ADLEntryClass/run() at global/runtime::ADLEntry()Så, det är principen för att skriva och läsa data till och från filen. Hela koden bör se ut så:
Slutligen:
Notera: Om du kör koden som den är så händer inget, därför ska du skriva innan funktionerna detta: writeToFile(fil); om du vill skriva
och om du vill läsa skriver du readFromFile(fil);
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
var minXML:XML = <rooten> <sitenamn>FlashGuru</sitenamn><siteurl>www.flashguru.se</siteurl></rooten>;
var filMapp:File = File.applicationStorageDirectory;
var fil:File = filMapp.resolvePath("minfil.xml");
function writeToFile(_file:File, _data:XML):void{
var dataString:String = _data.toXMLString();
var fs:FileStream = new FileStream();
fs.open(_file, FileMode.WRITE);
fs.writeUTFBytes(dataString);
fs.close();
}
function readFromFile(_file:File):void{
var fs:FileStream = new FileStream();
fs.open(_file, FileMode.READ);
var filDataXML:XML = new XML(fs.readUTFBytes(fs.bytesAvailable));
fs.close();
trace(filDataXML);
}
Så klart kan du skapa textfält och sedan hämta data från dessa och lagra i XML-strukturen och sedan läsa in igen.
Exempel:
Exempelvis kan du använda följande kod (Kopiera och klistra in i ditt AIR projekt):
//
// Skapad av Danel Kirch
// för Flashguru.se @ 2010//
// Koden är CAPAR anpassad (Copy-and-Paste-and-Run)
// Denna kod får kopieras och redigeras samt, användas för privat och kommerciell -bruk.
//
// Importera bibliotek
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldType;
import flash.display.Sprite;
// Skapa variablar för 3 textfält
var tfFNamn:TextField;
var tfENamn:TextField;
var tfAlder:TextField;
// Skapa själva textfälten som är wrappade i en funktion längre ned
skapaTextFields(50,"Skriv ditt namn här...","Skriv ditt efternamn här...","Skriv din ålder här...");
// Skapa 2 knappar, en för laddning och en för sparning
var btnSave:Sprite = new Sprite();
btnSave.graphics.beginFill(0XFFAA00, .3);// Gul/orange knapp
btnSave.graphics.drawRect(0,0, 100, 30);
btnSave.graphics.endFill();
btnSave.x = 50;
btnSave.y = 200;
var tfSave:TextField = new TextField();
tfSave.selectable = false;
tfSave.text = "Ladda från fil";
tfSave.height = 14;
tfSave.y = -14;
btnSave.addChild(tfSave);
addChild(btnSave);
var btnLoad:Sprite = new Sprite();
btnLoad.graphics.beginFill(0X55AA00, .3);// Grön knapp
btnLoad.graphics.drawRect(0,0, 100, 30);
btnLoad.graphics.endFill();
btnLoad.x = 210;
btnLoad.y = 200;
var tfLoad:TextField = new TextField();
tfLoad.selectable = false;
tfLoad.text = "Ladda från fil";
tfLoad.height = 14;
tfLoad.y = -14;
btnLoad.addChild(tfLoad);
addChild(btnLoad);
// Sätt eventlistener på knapparna
btnSave.addEventListener("mouseUp", handleData, false, 0, true);// Orange färgad
btnLoad.addEventListener("mouseUp", handleData, false, 0, true);// Grön färgad
// Skapa fil objekt och dess sökväg
var filMapp:File = File.applicationStorageDirectory;
var fil:File = filMapp.resolvePath("minfil.xml");
// Anropar samma event som när man trycker på Gröna knappen (för att ladda data från filen)
btnLoad.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
function handleData(m:MouseEvent):void {
switch (m.target) {
case btnSave :
trace("Sparar data från textfälten i den lokala filen");
var dittFNamn:String = tfFNamn.text;
var dittENamn:String = tfENamn.text;
var dinAlder:String = tfAlder.text;
// Skapa en string för XML'en
var xmlString:String = "<rooten><fnamn>" + dittFNamn + "</fnamn><enamn>" + dittENamn + "</enamn><alder>" + dinAlder + "</alder></rooten>";
// Anropa sparnings-funktion för XMLen och passera in String som en XML
writeToFile(fil,XML(xmlString));
tfFNamn.text = tfENamn.text = tfAlder.text = "";
break;
case btnLoad :
if (fil.exists) {
trace("Hittade lokala filen och läser dess innehåll");
// Läs filen och sätt dess data i textfälten
var minXML:XML = readFromFile(fil);
tfFNamn.text = minXML.fnamn;
tfENamn.text = minXML.enamn;
tfAlder.text = minXML.alder;
}
break;
}
}
// Funktion för att spara data i filen, konventerar inpasserade XMLen till en string
// OM filen inte finns från början, så skapas den i samma veva
function writeToFile(_file:File, _data:XML):void {
trace("Sparar filen...");
var dataString:String = _data.toXMLString();
var fs:FileStream = new FileStream();
fs.open(_file, FileMode.WRITE);
fs.writeUTFBytes(dataString);
fs.close();
}
// Funktion för att läsa data från filen, skapar en XML av den och returnerar som XML
function readFromFile(_file:File):XML {
trace("Läser från filen...");
var fs:FileStream = new FileStream();
fs.open(_file, FileMode.READ);
var filDataXML:XML = new XML(fs.readUTFBytes(fs.bytesAvailable));
fs.close();
return filDataXML;
}
// Skapar textfälten via kod
function skapaTextFields(_startX:Number, _namn:String, _enamn:String, _alder:String):void {
var textFormat:TextFormat = new TextFormat();
textFormat.font = "Verdana";
textFormat.size = 12;
tfFNamn = new TextField();
tfFNamn.defaultTextFormat = textFormat;
tfFNamn.x = _startX;
tfFNamn.y = 50;
tfFNamn.height = 20;
tfFNamn.border = true;
tfFNamn.type = TextFieldType.INPUT;
tfFNamn.text = _namn;
tfFNamn.width = 200;
addChild(tfFNamn);
tfENamn = new TextField();
tfENamn.defaultTextFormat = textFormat;
tfENamn.x = _startX;
tfENamn.y = tfFNamn.y + tfFNamn.height + 2;
tfENamn.height = 20;
tfENamn.border = true;
tfENamn.type = TextFieldType.INPUT;
tfENamn.text = _enamn;
tfENamn.width = 200;
addChild(tfENamn);
tfAlder = new TextField();
tfAlder.defaultTextFormat = textFormat;
tfAlder.x = _startX;
tfAlder.y = tfENamn.y + tfENamn.height + 2;
tfAlder.height = 20;
tfAlder.border = true;
tfAlder.type = TextFieldType.INPUT;
tfAlder.text = _alder;
tfAlder.width = 200;
addChild(tfAlder);
}