跳转到内容

Futurebasic/语言/fsref 遗留

来自维基教科书,为开放世界提供开放书籍

FSRef 结构 - 遗留讨论

[编辑 | 编辑源代码]

在 OS X 中访问文件和文件夹的首选方法。

与仅限于 31 个字符的文件和文件夹名的 FSSpec 不同,FSRef 被构建为处理长的 Unicode 文件名和 OS X 更强大的需求。

在 FB 和 FBtoC 中讨论 FSRef 会很困难,因为没有将它们的功能与 FSSpec 进行比较。虽然 FSSpec 在 Carbon API 中可能已经过时(与流行的传说相反,它们尚未被弃用),但 FB 文件和文件夹功能是为使用 FSSpec 而设计的(FB 的旧“工作目录”功能早已过时,并且在 OS X 中不再推荐也不支持)。尽管如此,FB 可以适应处理 FSRef,而不会带来太多痛苦。另一方面,FBtoC 提供对 FSRef 的原生支持。

虽然用户能够直接访问 FSSpec 的三个组成部分 - 文件或文件夹名、卷引用号和其父级的 ID,但 FSRef 对用户来说是“不透明的”。这意味着从 FSRef 获取信息需要辅助 Toolbox 函数。

当检查 FSSpec 和 FSRef 的结构时,它们之间的差异显而易见(这些定义在 Carbon Files.h 头文件中找到)

FSSpec 结构

struct FSSpec {
  short         vRefNum;
  long          parID;
  StrFileName   name;          /* a Str63 */
};

FSRef 结构

struct FSRef {
  UInt8         hidden[80];    /* private to File Manager*/
};

可能对你的代码产生最大影响的差异是,FSRef 不能表示不存在的项,并且 FSRef 的不透明数据结构(在上面定义为 80 字节的隐藏数组)没有记录。特别是,与 FSSpec 不同,FSRef 不包含它所引用的项的名称。当你考虑到 Mac OS X 允许使用包含 Unicode 字符的文件名时,这一点就不足为奇了,文件名最大长度为 255 个 UniChars。与 FSSpec 的静态功能相比,FSRef 是动态的。

在 FB 中创建 FSRef 文件引用

[编辑 | 编辑源代码]

FB 的文件和文件夹函数是在 FSSpec 盛行的时代编写的。它们最常见的用途之一是在使用 FB 的 Files$ 函数打开文件或文件夹时。在这里,我们看到 FB 的代码来获取文本文件的 FSSpec

dim as FSSpec   fs
dim as str255  fStr

fStr = Files$( _FSSpecOpen, "TEXT", "Open text file...", fs )
  long if ( fStr[0] )
    // Do something with your text file FSSpec
  xelse
    // User canceled
  end if

为了使用 FB 的 Files$ 函数获取更灵活、更适用于 OS X 的 FSRef,需要将生成的 FSSpec 转换为 FSRef。这需要几行额外的代码

dim as FSSpec  fs
dim as FSRef   fref
dim as str255  fStr

fStr = Files$( _FSSpecOpen, "TEXT", "Open text file...", fs )
  long if ( fStr[0] )
    // Convert FSSpec to FSRef
    err = fn FSpMakeFSRef( #fs, @fref)
    long if ( err == _noErr )
      // Do something with your text file FSRef
     end if
  xelse
    // User canceled
  end if

在 FBtoC 中创建 FSRef 文件引用

[编辑 | 编辑源代码]

最后,FBtoC 提供对 FSRef 的原生处理,允许我们的函数这样编写

dim as FSRef   fref
dim as str255  fStr

fStr = files$( _FSRefOpen, "TEXT", "Open text file...", fsRef )
  long if ( fStr[0] )
    // Do something with your text file FSRef
  xelse
    // User canceled
  end if

在 FB 和 FBtoC 中创建 FSRef 文件引用

[编辑 | 编辑源代码]

结合这些简单的方法,就是这个示例,它在 FB 和 FBtoC 中都返回 FSRef

 dim as str255  fileName, s
 dim as FSSpec   fs
 dim as FSRef    fsRef
 dim as OSErr    err
'~'1

 #if ndef _FBtoC

 s = "Get file FSSpec in FB"
 fileName = files$( _FSSpecOpen,, s, fs )
  long if ( fileName[0] )
    // Convert FSSpec to FSRef
    err = fn FSpMakeFSRef( #fs, @fsRef)
    long if (err == _noErr )
      // Do something with your FSRef
    end if
  xelse
    // User canceled
  end if

 #else

 s = "Get file FSRef in FBtoC"
 fileName = files$( _FSRefOpen,, s, fsRef )
   long if fileName[0]
    //  Do something with your FSRef
   xelse
     // User canceled
   end if

 #endif

使用 FSSpec 和 FSRef 获取文件名

[编辑 | 编辑源代码]

要从 FSSpec 获取文件名,用户只需像这样查看其内部结构或记录

myFileName = myFSSpec.name

当然,生成的文件名限制为 31 个字符,并且对于 OS X 中更长的文件名,它会被截断,并带有垃圾字符。

从 FSRef 获取文件名稍微困难一些,但此函数应该可以完成任务

local fn GetLongFileNameFromFSRef$( fsRef as ^FSRef )
 dim as str255      @ name
 dim as HFSUniStr255    hsfName
 dim as CFStringRef     cfStr
 dim as OSErr           err
 dim as boolean       result
'~'1

 err = fn FSGetCatalogInfo( #fsRef, _kFSCatInfoNone, #0, hsfName, #0, #0)
 if err then stop "FSGetCatalogInfo Error:" + str$( err )
  long if ( err == _noErr )
    cfStr = fn CFStringCreateWithCharacters( 0,hsfName.unicode[0], hsfName.length )
      long if ( cfStr )
        result = fn CFStringGetPascalString( cfStr, @name, sizeof( name ), _kCFStringEncodingMacRoman )
        CFRelease( cfStr )
      end if
  end if

end fn = name
华夏公益教科书