比方說,我想使用單個物件來表示一個檔案,并且我想獲取它的檔案名(或路徑),以便我可以使用該名稱來洗掉檔案或用于其他標準庫程序。我想要一個可以與所有可用的檔案相關標準庫程序一起使用的抽象。
我發現FileInfo但在我的研究中我沒有找到獲取檔案名的程序。File并且FileHandle從軟體工程的角度來看非常無用,因為它們不提供方便的抽象并且沒有成員。
Nim 中是否有檔案抽象(物件),它提供FileInfo對檔案名的快速訪問,以便檔案不需要多個程序引數?
uj5u.com熱心網友回復:
Nim 或任何其他語言中沒有這樣的抽象,僅僅是因為您要求對大多數檔案系統進行不可能的事情。考慮FileInfo結構及其linkCount欄位,它告訴您檔案物件具有的硬鏈接數。但是,除了構建和更新整個檔案系統的資料庫之外,無法從一個或所有這些鏈接中獲取檔案名。
雖然大多數檔案系統允許通過路徑訪問檔案,但很少有檔案系統提供檔案路徑,因為它們實際上不需要!一個例子是 Unix 檔案系統,其中一個行程通過路徑打開檔案,然后洗掉路徑而不關閉檔案。雖然保持檔案打開的行程處于活動狀態,但該檔案實際上不會消失,因此您會遇到沒有路徑的檔案。
處理路徑的問題,尤其是考慮到跨平臺應用程式,涉及它自己的蠕蟲:如果將路徑存盤為字串,路徑分隔符是什么以及如何轉義它?您的檔案系統是否支持需要特殊情況處理的卷?路徑使用什么字串編碼來滿足所有用戶?只是編碼問題需要大量的表和轉換,這會阻礙所有其他希望獲得像句柄這樣的檔案來讀取或寫入位元組的 API。
AFileInfo只是給定時間檔案狀態的快照,檔案句柄是您可以操作的活動檔案物件,而路徑(如果您的檔案系統支持硬鏈接,則為許多路徑)只是 end 的一個方便名稱用戶。
這些都是非常不同的東西,這就是為什么它們是分開的。您的應用程式可能需要比其他程式員愿意容忍的更復雜的抽象,因此請創建自己的抽象,將您需要的所有單個部分組合在一起。例如,考慮以下結構:
import os
type
AppFileInfo = object
fileInfo: FileInfo
file: File
oneOfMany: string
proc changeFileExt(appFileInfo: AppFileInfo, ext: string): string =
changeFileExt(appFileInfo.oneOfMany, ext)
proc readAll(appFileInfo: AppFileInfo): string =
readAll(appFileInfo.file)
這些 proc 只是模仿各自的標準庫 API,但使用更復雜的結構作為輸入并根據需要對其進行轉換。如果您擔心由于額外的 proc 呼叫而無法優化此抽象,您可以改用模板。
但是,如果您遵循這條路線,在某些時候您將不得不問自己一個物件的生命周期是多少AppFileInfo:您是否使用路徑創建它?你是從檔案句柄創建的嗎?訪問file部分代碼中的欄位是否安全或未正確初始化?當出現問題時,您是否回傳錯誤或拋出例外?也許當您開始問自己這些問題時,您會意識到它們非常特定于應用程式,并且很難概括為每個用例。因此,這樣一個復雜的物件在語言標準庫中沒有多大意義。
uj5u.com熱心網友回復:
我自己創建了缺少的解決方案。我基本上File使用全域封裝表擴展了型別。由于 UFCS,像這樣擴展型別在 Nim 中可能是一個有用的習慣用法。
import tables
type FileObject = object
file : File
mode : FileMode
path : string
proc initFileObject(name: string; mode: FileMode; bufsize = -1) : FileObject =
result.file = open(name, mode, bufsize)
result.path = name
result.mode = mode
var g_fileObjects = initTable[File, FileObject]()
template get(this: File) : var FileObject = g_fileObjects[this]
proc openFile*(filepath: string; mode: FileMode = fmRead; bufsize = -1) : File =
var fileObject = initFileObject(filepath, mode, bufsize)
result = fileObject.file
g_fileObjects[result] = fileObject
proc filePath*(this: File) : string {.raises: KeyError.} =
return this.get.path
proc fileMode*(this: File) : FileMode {.raises: KeyError.} =
return this.get.mode
from os import tryRemoveFile
proc closeOrDeleteFile[delete = false](this: File) : bool =
result = g_fileObjects.hasKey(this)
if result:
when delete:
result = this.filepath.tryRemoveFile()
g_fileObjects.del(this)
this.close()
proc closeFile*(this: File) : bool = this.closeOrDeleteFile[:false]
proc deleteFile*(this: File) : bool = this.closeOrDeleteFile[:true]
現在你可以寫
var f = openFile("myFile.txt", fmWrite)
var g = openFile("hello.txt", fmWrite)
echo f.filePath
echo f.deleteFile()
g.writeLine(g.filePath)
echo g.closeFile()
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/370685.html
