我刚从尼姆开始,所以这可能是一个简单的问题。我们需要对存储在文件中的数据进行许多查找。其中一些文件太大,无法加载到内存中,因此采用了mmapped方法。我可以通过memfile来mmap这个文件,并且我手上有一个指针或MemSlice。文件和内存区域是只读的,因此具有固定的大小.我希望能够以不可变的固定大小字节和char数组的形式访问数据,而无需复制它们,同时利用seqs、数组、字符串等现有的所有功能。所有的MemSlice / string方法都复制数据,这是公平的,但不是我想要的(在我的用例中也不需要)。
我理解数组、字符串等类型有一个指向数据和len字段的指针。但却找不到用指针和len创建它们的方法。我认为这与所有权有关,我认为这可能比我的份额更长。
let mm = memfiles.open(...)
let myImmutableFixesSizeArr = ?? # cast[ptr array[fsize, char]](mm.mem) doesn't compile as fsize needs to be const. Neither could I find something like let x: [char] = array_from(mm.mem, fsize)
let myImmutableFixedSizeString = mm[20, 30].to_fixed_size_immutable_string # Create something that is string like so that I can use all the existing string methods.
更新:我找到了解释如何使用https://forum.nim-lang.org/t/4680#29226的OpenArray,但是只允许OpenArray作为函数参数,如果我没有弄错的话,它的行为不像普通数组。
谢谢你的帮忙
发布于 2021-02-04 14:40:12
不复制就不可能将内存中的原始字符数组(ptr UncheckedArray[char]
)转换为string
,只能将其转换为openArray[char]
(或cstring
)。
因此,不可能使用期望使用string
的procs,只使用那些接受openArray[T]
或openArray[char]
的
幸运的是,当发送到proc时,openArray[T]
的行为与seq[T]
完全一样。
({.experimental:"views".}
确实允许将一个openArrayT赋值给局部变量,但它还没有做好生产准备)
您可以使用memSlices
迭代器在不复制的情况下循环遍历memFile中的分隔块:
import memfiles
template toOpenArray(ms: MemSlice, T: typedesc = byte): openArray[T] =
##template because openArray isn't a valid return type yet
toOpenArray(cast[ptr UncheckedArray[T]](ms.data),0,(ms.size div sizeof(T))-1)
func process(slice:openArray[char]) =
## your code here but e.g.
## count number of A's
var nA: int
for ch in slice.items:
if ch == 'A': inc nA
debugEcho nA
let mm = memfiles.open("file.txt")
for slice in mm.memSlices:
process slice.toOpenArray(char)
或者,要处理文件中间表示的char数组,可以使用指针算法。
import memfiles
template extractImpl(typ,pntr,offset) =
cast[typ](cast[ByteAddress](pntr)+offset)
template checkFileLen(memfile,len,offset) =
if offset + len > memfile.size:
raise newException(IndexDefect,"file too short")
func extract*(mm: MemFile,T:typedesc, offset:Natural): ptr T =
checkFileLen(mm,T,offset)
result = extractImpl(ptr T,mm.mem,offset)
func extract*[U](mm: MemFile,T: typedesc[ptr U], offset: Natural): T =
extractImpl(T,mm.mem,offset)
let mm = memfiles.open("file.txt")
#to extract a compile-time known length string:
let mystring_offset = 3
const mystring_len = 10
type MyStringT = array[mystring_len,char]
let myString:ptr MyStringT = mm.extract(MyStringT,mystring_offset)
process myString[]
#to extract a dynamic length string:
let size_offset = 14
let string_offset = 18
let sz:ptr int32 = mm.extract(int32,size_offset)
let str:ptr UncheckedArray[char] = mm.extract(ptr UncheckedArray[char], string_offset)
checkFileLen(mm,sz[],string_offset)
process str.toOpenArray(0,sz[]-1)
https://stackoverflow.com/questions/66014574
复制相似问题