在 Nim 中是否有一个文件对象来获取文件的路径或名称?
Is there a file object to get path or name of a file in Nim?
比方说,我想用一个对象来表示一个文件,我想获取它的文件名(或路径),以便我可以使用该名称删除文件或用于其他标准图书馆手续。我想要一个单一的抽象,它可以与所有可用的文件相关的标准库过程一起使用。
我找到了 FileInfo
,但在我的研究中我没有找到获取文件名的过程。 File
和 FileHandle
从软件工程的角度来看非常无用,因为它们没有提供方便的抽象并且没有成员。
Nim 中是否有一种文件抽象(对象),它提供对 FileInfo
以及文件名的快速访问,以便一个文件不需要多个过程参数?
在 Nim 或任何其他语言中没有这样的抽象,只是因为您要求对大多数文件系统做不可能的事情。考虑 FileInfo 结构及其 linkCount
字段,它告诉您文件对象具有的硬链接数。但是没有办法从一个或所有这些链接中获取文件名,除非自己构建和更新整个文件系统的数据库。
虽然大多数文件系统允许通过路径访问文件,但很少有文件系统提供文件的路径,因为它们实际上不需要路径!一个例子是 Unix 文件系统,其中一个进程通过路径打开文件,然后在不关闭文件的情况下删除路径。虽然保持文件打开的进程处于活动状态,但该文件实际上不会消失,因此您会遇到文件没有路径的情况。
处理路径的问题,尤其是考虑到跨平台应用程序,涉及其自身的问题:如果将路径存储为字符串,路径分隔符是什么以及如何 转义 它?您的文件系统是否支持需要特殊情况处理的卷?路径使用什么字符串编码来满足所有用户?仅仅是编码问题就需要大量的表格和转换,这会使其他 API 希望只获得一个像句柄这样的文件来读取或写入字节。
A FileInfo
只是给定时间文件状态的快照,文件句柄是您可以操作的 live 文件对象,并且一个路径(如果您的文件系统支持硬链接,则为多个路径)只是最终用户的方便名称。
这些都是非常不同的东西,这就是为什么它们是分开的。您的应用程序可能需要比其他程序员愿意容忍的更复杂的抽象,因此创建自己的抽象,将您需要的所有单独部分结合在一起。例如,考虑以下结构:
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 调用而无法优化此抽象,您可以使用 a template instead.
但是,如果您遵循这条路线,在某些时候您将不得不问自己,AppFileInfo
对象的 lifetime 是什么:您使用路径?您是从文件句柄创建的吗?访问部分代码中的 file
字段是否安全,或者它是否未正确初始化?当出现问题时,你会 return 出错或抛出异常吗?也许当您开始问自己这些问题时,您会意识到它们是非常特定于应用程序的,并且很难针对每个用例进行概括。因此,如此复杂的对象在语言标准库中没有多大意义。
我自己创建了缺少的解决方案。我基本上使用全局封装的 table 扩展了 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()
比方说,我想用一个对象来表示一个文件,我想获取它的文件名(或路径),以便我可以使用该名称删除文件或用于其他标准图书馆手续。我想要一个单一的抽象,它可以与所有可用的文件相关的标准库过程一起使用。
我找到了 FileInfo
,但在我的研究中我没有找到获取文件名的过程。 File
和 FileHandle
从软件工程的角度来看非常无用,因为它们没有提供方便的抽象并且没有成员。
Nim 中是否有一种文件抽象(对象),它提供对 FileInfo
以及文件名的快速访问,以便一个文件不需要多个过程参数?
在 Nim 或任何其他语言中没有这样的抽象,只是因为您要求对大多数文件系统做不可能的事情。考虑 FileInfo 结构及其 linkCount
字段,它告诉您文件对象具有的硬链接数。但是没有办法从一个或所有这些链接中获取文件名,除非自己构建和更新整个文件系统的数据库。
虽然大多数文件系统允许通过路径访问文件,但很少有文件系统提供文件的路径,因为它们实际上不需要路径!一个例子是 Unix 文件系统,其中一个进程通过路径打开文件,然后在不关闭文件的情况下删除路径。虽然保持文件打开的进程处于活动状态,但该文件实际上不会消失,因此您会遇到文件没有路径的情况。
处理路径的问题,尤其是考虑到跨平台应用程序,涉及其自身的问题:如果将路径存储为字符串,路径分隔符是什么以及如何 转义 它?您的文件系统是否支持需要特殊情况处理的卷?路径使用什么字符串编码来满足所有用户?仅仅是编码问题就需要大量的表格和转换,这会使其他 API 希望只获得一个像句柄这样的文件来读取或写入字节。
A FileInfo
只是给定时间文件状态的快照,文件句柄是您可以操作的 live 文件对象,并且一个路径(如果您的文件系统支持硬链接,则为多个路径)只是最终用户的方便名称。
这些都是非常不同的东西,这就是为什么它们是分开的。您的应用程序可能需要比其他程序员愿意容忍的更复杂的抽象,因此创建自己的抽象,将您需要的所有单独部分结合在一起。例如,考虑以下结构:
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 调用而无法优化此抽象,您可以使用 a template instead.
但是,如果您遵循这条路线,在某些时候您将不得不问自己,AppFileInfo
对象的 lifetime 是什么:您使用路径?您是从文件句柄创建的吗?访问部分代码中的 file
字段是否安全,或者它是否未正确初始化?当出现问题时,你会 return 出错或抛出异常吗?也许当您开始问自己这些问题时,您会意识到它们是非常特定于应用程序的,并且很难针对每个用例进行概括。因此,如此复杂的对象在语言标准库中没有多大意义。
我自己创建了缺少的解决方案。我基本上使用全局封装的 table 扩展了 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()