Futurebasic/語言/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 標頭檔案中找到)
struct FSSpec {
short vRefNum;
long parID;
StrFileName name; /* a Str63 */
};
struct FSRef {
UInt8 hidden[80]; /* private to File Manager*/
};
可能對你的程式碼產生最大影響的差異是,FSRef 不能表示不存在的項,並且 FSRef 的不透明資料結構(在上面定義為 80 位元組的隱藏陣列)沒有記錄。特別是,與 FSSpec 不同,FSRef 不包含它所引用的項的名稱。當你考慮到 Mac OS X 允許使用包含 Unicode 字元的檔名時,這一點就不足為奇了,檔名最大長度為 255 個 UniChars。與 FSSpec 的靜態功能相比,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 的原生處理,允許我們的函式這樣編寫
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
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 獲取檔名,使用者只需像這樣檢視其內部結構或記錄
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