AIR文件操作

来源:互联网 发布:象棋路边残局知乎 编辑:程序博客网 时间:2024/05/21 18:47
整理]AIR文件操作 

2009-03-12 14:37:53|  分类:昨日。记 |  标签:|字号订阅

       AIR提供了让您能用来访问、创建、管理文件与目录的类。这些类被放置在flash.filesystem包中,也就是下面那三个类:

类描述FileFile对象代表一个文件或目录的路径。您可以用file对象建立一个指向文件或目录的指针,以作用于文件或目录。FileModeFileMode类定义在FileStream类的open()和openAsync()方法中使用的字符串常量参数。
这些方法的FileMode参数确定了文件打开后FileStream对象可用的功能,包括写入、读取、追加和更新。FileStreamFileStream对象打开文件以便读写数据。当创建一个File对象指向一个新的或已存在的文件后,您将该指针传递给FileStream对象,就可以用FileStream来打开并操作文件数据。

File类中的某些方法分别有同步和异步两种版本:

  • File.copyTo() 和 File.copyToAsync()
  • File.deleteDirectory() 和File.deleteDirectoryAsync()
  • File.deleteFile() 和File.deleteFileAsync()
  • File.getDirectoryListing() 和File.getDirectoryListingAsync()
  • File.moveTo() 和File.moveToAsync()
  • File.moveToTrash() 和File.moveToTrashAsync()

       同样,FileStream是以同步或异步方式来操作数据,取决于FileStream对象如何打开文件:是调用open()方法还是调用openAsync()方法。

       异步版本的处理过程在后台运行,当执行完成或产生错误时触发相应事件。其他代码可以在这些异步操作后台运行的同时执行。使用异步版本操作,你必须设置事件监听,使用File或FileStream对象的addEventListener()方法调用相应函数。

       同步版本使您不需要依赖设置事件监听,直接写简单的代码。然而,其他代码无法在同步方法执行时执行,重要的进程(比如显示对象渲染和动画播放)可能被暂停。

文件对象是啥?
文件对象(File对象)是在文件系统中指向文件或目录的指针。由于安全原因,只在AIR中可用。

  1. 获取特定目录,包括用户目录、用户文档目录、该应用程序启动的目录和程序目录
  2. 拷贝文件和目录
  3. 移动文件和目录
  4. 删除文件和目录(或移至回收站)
  5. 列出某目录中的文件和目录
  6. 创建临时文件和文件夹
  7. 创建目录
  8. 读取文件信息
  9. 获取文件系统信息

在AIR中,我们用FileStream读写文件的前提就是用File对象来指向文件。

那么文件对象具体怎么玩呢?

功能1、指向目录和文件
File对象有两个属性都能定义文件路径,它们是nativePath和url。nativePath是在特定平台使用的文件路径(主要就是Windows和MacOs上的路径表示不同),url则是统一的”file:///c:/Sample%20directory/test.txt”这样的表示方法。

我们来看几个指向目录的实例,其中1-7演示了如何获取特殊目录

    1. var file:File =File.userDirectory;//指向用户文件夹
    1. var file:File =File.documentsDirectory;//指向用户文档文件夹
    1. var file:File =File.desktopDirectory;//指向桌面
    1. var file:File =File.applicationStorageDirectory;//指向应用程序存储目录

    (参见AIR的URL方案

    1. var dir:File =File.applicationDirectory;//应用程序安装目录
    1. var dir:File =File.getRootDirectories();//文件系统根目录
  1. 还有一招,指向请求启动该应用程序的目录,先空着,以后补上。参考资料见《Capturing command
    line arguments》
    1. var file:File =new File();
    2. file.nativePath ="C:Mousebomb";

    //(windows平台)指向一个具体的目录,这里使用了nativePath属性,”C:Mousebomb”只适用windows中。

  2. var file:File = File.userDirectory;
    file = file.resolvePath(”Mousebomb”);
    //跳转到用户目录下的Mousebomb目录
    1. var urlStr:String ="file:///C:/Mousebomb/";
    2. var file:File =new File()
    3. file.url =urlStr;
    4. //指向c盘下的Mousebomb目录,这里使用了url属性
    1. /*让用户选择目录*/
    2. var file:File =new File();
    3. file.addEventListener(Event.SELECT,dirSelected);
    4. file.browseForDirectory("Select a directory");
    5. function dirSelected(e:Event):void{
    6. trace(file.nativePath);
    7. }

下面看看指向文件的实例:

  1. 指向明确的文件地址:
    1. var file:File =File.applicationStorageDirectory;
    2. file = file.resolvePath("Flashj.txt");
  2. 使用url属性的例子:
    1. var urlStr:String ="file:///C:/Mousebomb/Flashj.txt";
    2. var file:File =new File()
    3. file.url =urlStr;
  3. 当然你也可以直接这样写
    1. var urlStr:String ="file:///C: /Mousebomb/Flashj.txt";
    2. var file:File =new File(urlStr);
    3. //url中的空格会被%20替换
  4. 使用nativePath属性:
    1. var file:File =new File();
    2. file.nativePath ="C:/ Mousebomb/Flashj.txt";
  5. 或者
    1. var file:File =new File("C:/ Mousebomb/Flashj.txt");
    2. //(Windows下)
  6. 通过对话框让用户选择文件
    实现这个功能需要认识三个方法:
    browseForOpen()
    browseForSave()
    browseForOpenMultiple()
    三个方法都是异步的,browseForOpen() 和 browseForSave()方法在用户选择文件时会触发select事件,在选择了某文件时,File指向选择的文件。 而browseForOpenMultiple()方法会触发selectMultiple事件,该事件属于FileListEvent型,它的属性中具有指向所选文件的File对象数组。
    例子:

    1. var fileToOpen:File =File.documentsDirectory;
    2. selectTextFile(fileToOpen);
    3. function selectTextFile(root:File):void
    4. {
    5. var txtFilter:FileFilter =new FileFilter("Text","*.as;*.css;*.html;*.txt;*.xml");
    6. root.browseForOpen("Open",[txtFilter]);
    7. root.addEventListener(Event.SELECT,fileSelected);
    8. }
    9. function fileSelected(event:Event):void
    10. {
    11. trace(fileToOpen.nativePath);
    12. }

功能2、拷贝文件和目录
拷贝文件使用到的方法有copyTo()和copyToAsync(),详见AIR文件基础,前者为同步方法,后者为异步方法。
要拷贝文件,需要创建2个File对象,一个指向原文件,一个指向目标文件。像下面两例:
1.同步拷贝例:

  1. var original:File =File.documentsDirectory.resolvePath("Mousebomb/FlashJ.txt");
  2. var newFile:File =File.resolvePath("Mousebomb/FlashJcn.txt");
  3. original.copyTo(newFile,true);

第二个参数true表示覆盖存在的文件,默认值是false,若设置为false,而拷贝的目标文件已经存在,则AIR会发出IOErrorEvent事件。
2.异步拷贝例:

  1. var original =File.documentsDirectory;
  2. original = original.resolvePath("Mousebomb/FlashJ.txt");
  3. var destination:File =File.documentsDirectory;
  4. destination = destination.resolvePath("FlashJ/FlashJcn.txt");
  5. original.addEventListener(Event.COMPLETE,fileCopyCompleteHandler);
  6. original.addEventListener(IOErrorEvent.IO_ERROR,fileCopyIOErrorEventHandler);
  7. original.CopyToAsync(destination);
  8. function fileCopyCompleteHandler(event:Event):void{
  9. trace(event.target);// [object File]
  10. }
  11. function fileCopyIOErrorEventHandler(event:IOErrorEvent):void{
  12. trace("I/O Error.");
  13. }

功能3、移动文件和目录
移动文件使用的方法有moveTo()和MoveToAsync(),不仅长相类似,连使用方法都与拷贝文件一样,可以直接参考上文。

功能4、删除文件和目录(或移至回收站)
deleteFile()和deleteFileAsync()负责删除功能,而moveToTrash()和moveToTrashAsync()功能是移至回收站。先创建一个File对象指向某个文件或目录,然后执行四个方法之一,处理异步方法要加事件监听。

  1. var file:File =File.documentsDirectory.resolvePath("DeleteMe.txt");
  2. file.moveToTrash();

功能5、列出某目录中的文件和目录
可以使用getDirectoryListing()方法和getDirectoryListingAsync()方法获取某个目录下文件与子目录的File指针数组。
例如:

  1. var directory:File =File.documentsDirectory;
  2. var contents:Array =directory.getDirectoryListing();
  3. for (vari:uint =0; i <contents.length;i++)
  4. {
  5. trace(contents[i].name,contents[i].size);
  6. }

本例输出了用户文档目录中的文件名和大小。
若使用异步方法,例如:

  1. var directory:File =File.documentsDirectory;
  2. directory.getDirectoryListingAsync();
  3. directory.addEventListener(FileListEvent.DIRECTORY_LISTING,dirListHandler);
  4. function dirListHandler(event:FileListEvent):void
  5. {
  6. var contents:Array =event.files;
  7. for (vari:uint =0; i <contents.length;i++)
  8. {
  9. trace(contents[i].name,contents[i].size);
  10. }
  11. }

其中directoryListing事件对象中有个files属性,为目录下内容的File指针数组。

功能6、创建临时文件和文件夹
使用createTempFile()和createTempDirectory()方法可以创建临时文件和文件夹。
var temp:File = File.createTempFile(); //在系统临时文件夹下创建临时文件
createTempFile()方法会自动创建一个唯一的临时文件。
createTempDirectory ()方法会自动创建一个唯一的临时文件夹。
你可以用临时文件来临时存储应用程序回话中的信息。
由于临时文件不会自动删除,所以你可能得让应用程序在关闭前删除它。

功能7、创建目录
使用createDirectory()方法可以创建目录,例如:

  1. var dir:File =File.userDirectory.resolvePath("Mousebomb");
  2. dir.createDirectory();

这个例子在用户文件夹下创建了Mousebomb目录,如果Mousebomb目录存在,则不会作出操作。

功能8、读取文件信息
File类中包含以下属性,提供File对象所指向文件或目录的信息。

属性

描述

creationDate

创建日期

exists

是否存在

extension

扩展名,若无则为null

icon

该文件的图标对象

isDirectory

是否目录

modificationDate

修改日期

name

文件名(包括扩展名)

nativePath

特定平台使用的文件路径

parent

父级目录,若该File对象就是顶级则此属性为null

size

字节大小

url

统一资源定位符

详细参见AIR ActionScript 3.0 Language Reference for Adobe AIR.

功能9、获取文件系统信息
File类包含一下静态属性,提供有用的文件系统信息(主要是跨平台使用):

属性

描述

File.lineEnding

系统的行结束符

File.separator

系统的分隔符(Windows下为 Mac Os为/)

File.systemCharset

系统的默认文件编码,属于系统所使用的字符集

顺便插进Capabilities类包含的静态属性:

属性

描述

Capabilities.hasIME

当前运行的系统是否安装了输入法编辑器

Capabilities.language

当前运行的系统的语言编码

Capabilities.os

当前运行的操作系统

快速上手例:

例1.读xml

  1. var testXML:XML;
  2. var file:File =File.documentsDirectory.resolvePath("Mousebomb/test.xml");
  3. var fileStream:FileStream =new FileStream();
  4. fileStream.open(file,FileMode.READ);
  5. testXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
  6. fileStream.close();

例中使用readUTFBytes()方法读取内容并转换为XML对象。

  1. var
testXML:XML =<mousebomb><site>www.mousebomb.org</site><blog>www.flashj.cn</blog></mousebomb>;

  • var file:File = File.documentsDirectory.resolvePath("Mousebomb/test.xml");
  • var fileStream:FileStream = new FileStream();
  • fileStream.open(file, FileMode.WRITE);
  • var outputString:String = '<?xml version="1.0" encoding="utf-8"?>';
  • outputString += testXML.toXMLString();
  • fileStream.writeUTFBytes(outputString);
  • fileStream.close();

    写XML也一样简单,创建File对象和FileStream对象,使用writeUTFBytes()写入数据。

    工作流程

    要完成读写文件操作无非就是这几步:
    1. 创建File对象指向文件路径
    2. 初始化FileStream对象
    3. 使用FileStream的open()或openAsync()方法
    4. 若使用的是异步的openAsync()方法则需要为FileStream设置事件监听
    5. 加入所需的读写数据代码
    6. 完成文件操作后执行FileStream的close()方法

    使用FileStream要了解的知识

    1. FileMode
    FileStream的open()和openAsync()方法都包含一个fileMode参数,该参数用于设置:

    • 读取文件能力
    • 写入文件能力
    • 是否总在文件末尾追加数据(写数据时)
    • 文件不存在时如何操作(或文件的父级不存在时)

    具体值包括

    FileMode值

    描述

    FileMode.READ

    设置文件打开方式为只读

    FileMode.WRITE

    设置文件打开方式为写数据。若文件不存在,则创建之;若文件存在,则该文件所有存在数据被删除。

    FileMode.APPEND

    设置文件打开方式为追加。若文件不存在,则创建之;若存在,则文件所有存在数据不被覆盖,所有写入的数据从文件末尾开始。

    FileMode.UPDATE

    设置文件打开方式为读写。若文件不存在,则创建之。设置该模式通常用于随机读写访问文件。可以从文件的任意位置读取,写入数据时,只有写入位置的存在字节被覆盖,其他所有字节不受影响。

    2. position
    该属性决定下一个数据读写操作进行的位置。
    在读写操作前,设置position属性为文件中的有效位置,比如:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/site.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.open(myFile,FileMode.UPDATE);
    4. myFileStream.position =8;
    5. myFileStream.writeUTFBytes("hello");

    该例在位置8处写入UTF编码的字符串“hello”

    新打开的FileStream对象的position值为0,在读文件操作前,position的值必最小为0并小于文件总字节数。
    position的值仅会在以下情况下改变:

    1. 直接设置该属性值
    2. 执行读取操作
    3. 执行写入操作

    当执行读/写操作时,position的值会立即自增读/写的字节数,再次执行读/写操作时会从新的position位置开始:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/test.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.open(myFile,FileMode.UPDATE);
    4. myFileStream.position =4000;
    5. trace(myFileStream.position);// 4000
    6. myFileStream.writeBytes(myByteArray,0, 200);
    7. trace(myFileStream.position);// 4200

    position有一个例外:若文件打开模式设置为append(追加模式),则position属性不会随着写操作变化。在追加模式下,数据总是往文件末尾写,与position无关。

    异步方式打开文件,写数据操作在下一行代码执行时并没有结束。这怎么办呢?没关系,你可以按顺序的调用多个异步操作,AIR运行环境会逐个执行:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/test.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.openAsync(myFile,FileMode.WRITE);
    4. myFileStream.writeUTFBytes("hello");
    5. myFileStream.writeUTFBytes("world");
    6. myFileStream.addEventListener(Event.CLOSE,closeHandler);
    7. myFileStream.close();
    8. trace("started.");
    9. closeHandler(event:Event):void
    10. {
    11. trace("finished.");
    12. }

    该例会输出:
    started.
    finished.

    你可以在异步读写操作调用后,立即设置position的值,下次读写操作将换作从那个位置开始。比如:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/test.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.openAsync(myFile,FileMode.UPDATE);
    4. myFileStream.position =4000;
    5. trace(myFileStream.position);// 4000
    6. myFileStream.writeBytes(myByteArray,0, 200);
    7. myFileStream.position =300;
    8. trace(myFileStream.position);// 300

    3. 根据数据格式,选择合适的读写操作
    硬盘上的每个文件都是字节集合。在AS中,文件中的数据总是可以描述为ByteArray.比如下面的代码把文件数据读取到bytes这个ByteArray中:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/test.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.addEventListener(Event.COMPLETE,completed);
    4. myFileStream.openAsync(myFile,FileMode.READ);
    5. var bytes:ByteArray =new ByteArray();
    6. function completeHandler(event:Event):void
    7. {
    8. myFileStream.readBytes(bytes,0, myFileStream.bytesAvailable);
    9. }

    下面的代码把数据从bytes这个ByteArray中写入文件:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/test.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.open(myFile,FileMode.WRITE);
    4. myFileStream.writeBytes(bytes,0, bytes.length);

    往往我们并不希望把数据作ByteArray处理,有时候要处理的文件是特定格式,比如文件中的数据是字符串。因此FileStream类也包含ByteArray以外的数据格式读写方法,比如readMultiByte()方法,可将文件读取暂存为字符串,如下代码:

    1. var myFile:File =File.documentsDirectory.resolvePath("Mousebomb/test.txt");
    2. var myFileStream:FileStream =new FileStream();
    3. myFileStream.addEventListener(Event.COMPLETE,completed);
    4. myFileStream.openAsync(myFile,FileMode.READ);
    5. var str:String ="";
    6. function completeHandler(event:Event):void
    7. {
    8.    str =myFileStream.readMultiByte(myFileStream.bytesAvailable,"iso-8859-1");
    9. }

    readMultiByte()的第二个参数(本例中为“iso-8859-1”)指定了ActionScript用来解释的文本格式。ActionScript支持通用字符集编码,具体罗列在http://livedocs.macromedia.com/flex/2/langref/charset-codes.html

    FileStream 类还具有readUTFBytes()方法,从读缓存中以UTF-8字符集读取数据。由于UTF8字符集为可变长,读缓存末尾数据并不一定是完整字符,所以不要在处理progress 事件的方法中使用readUTFBytes()方法(用readMultiByte()读取可变长字符编码也应遵循此项),而应在FileStream的complete事件发生时读取完整数据集。

    同样,有类似的写操作writeMultiByte()和writeUTFBytes(),用来处理字符串对象和文本文件。

    readUTF()和writeUTF()方法同样是读写文本数据,不过它们假定文本数据在指定文本数据长度之前,该文本数据是不在标准文本文件里普遍应用的。
    有些UTF编码文本文件以一个UTF-BOM(Byte Order Mark)字符开头,像编码格式(如UTF16和UTF32)一样,也声明字节序。

    readObject() 和writeObject()方法便于为复杂AS对象存取数据,数据作AMF(ActionScript Message Format)编码,此格式为ActionScript私有,AIR、Flash Player、Flash Media Server、Flex Data Services以外的程序都没有操作该格式的内建API。
    此外还有一些读写操作,像readDouble()和writeDouble()之类的,使用它们需确保所操作文件格式与之对应。

    一般的文件结构往往比文本文件要复杂的多。比如mp3文件包含只能被mp3解压解码算法解释的压缩数据格式。其他文件,像图片、数据库、应用程序档案等等都有不同的结构,要想用AS操作它们的数据,得对其结构十分了解。