2017-06-13 269 views
0

我不是一个不安全的软件包专家 - 我也不是一个经验丰富的C程序员。我正尝试在go中使用mmap syscall读取一个大文件> 1G。我做mmap和munmap的原因有很多,而不是读取,写入I/O。这是在旁边 - 我可以在测试中写入文件,当我从文件读取时,我可以确定字节长度匹配,但我无法读取此字符串文件的内容:(可以有人建议一些阅读?需要做进一步走一点,这里的一些代码,我做了样品的测试:mmap系统调用使用Golang的读取

filename := "/tmp/dd_file.db" 
f, err := os.OpenFile(filename, os.O_RDWR, 0666) 
defer f.Close() 
if err != nil { 
    fmt.Printf("error opening file: %v", err) 
} 
stat, _ := f.Stat() 
size := stat.Size() 
fmt.Printf("[READ-ONLY] : size was : %+v\n", size) 
got := make([]byte, size) 
if _, err := f.ReadAt(got, 0); err != nil && err != io.EOF { 
    panic(err) 
} 
want, err := ioutil.ReadFile(filename) 
if err != nil { 
    fmt.Printf("[READ-ONLY] : ioutil.ReadFile: %v", err) 
} 
// going to change the file size now, punch in a few things 
t := unsafe.Sizeof("") 
if err != nil { 
    fmt.Println(err) 
    os.Exit(1) 
} 
_, err = f.Seek(int64(t-1), 0) 
if err != nil { 
    fmt.Println(err) 
    os.Exit(1) 
} 
_, err = f.Write([]byte(" ")) 
if err != nil { 
    fmt.Println(err) 
    os.Exit(1) 
} 
mmap, err := syscall.Mmap(int(f.Fd()), 0, int(t), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) 
if err != nil { 
    fmt.Println(err) 
    os.Exit(1) 
} 
// not too sure on reading data on string - doesnt work as expected. 
map_array := (*[10000]string)(unsafe.Pointer(&mmap[0])) 
map_array[0] = "yellow!" 
err = syscall.Munmap(mmap) 
if err != nil { 
    fmt.Println(err) 
    os.Exit(1) 
} 
newStat, _ := f.Stat() 
newSize := newStat.Size() 
fmt.Printf("[mmap() RW] : size was : %+v\n", newSize) 
got = make([]byte, newSize) 
if _, err := f.ReadAt(got, 0); err != nil && err != io.EOF { 
    panic(err) 
} 
if len(got) == len(want) { 
    fmt.Println("well the lengths are equal atleast??!") 
} 
if !bytes.Equal(got, want) { 
    fmt.Printf("\n [mmap() RW] : works! got %d \n want %d", len(got), len(want)) 
} 

显然这工作正常 - 但如果我想通过mmap()的上mmapped文件读取,怎么做我从这些字节中读取字符串(我有一种感觉,在某处我可能需要使用编码包,但是随后StringHeader在不安全的文档上使我困惑)

建议:

+0

也许我不明白你的意思。如果你正在使用'mmap',是不是该文件的内容可以作为'[] byte'?“。要获取字符串,可以使用'string(mmap [:100])'< - 将前100个字节转换为字符串。或者你可以使用['bytes.Buffer'](https://golang.org/pkg/bytes/#Buffer)(但可能不是你想要的,因为你避免使用io.reader/io.writer模式) – putu

+0

I要避免读者 - 但我的问题是,我怀疑,通过mmap写入字符串字节它不是冲洗合法字符只是一些控制字符 - 我怀疑我的编码可能会搞砸 - 任何建议? –

+0

看看['https://github.com/riobard/go-mmap'](https://github.com/riobard/go-mmap)。该软件包可以用作'mmap'用法的参考。为了将字符串写入'mmap',你可以做'copy(mmap,[] byte(“Your string”))''。 – putu

回答

0

由于@putu的评论指出,一个字节的片可以通过一个简单的类型转换转换为字符串:

asStr = string(byteSlice) // entire slice as a string 
partStr = string(byteSlice[:100]) // first 100 bytes as a string 
+0

这不起作用 - 我正在做一个不安全的指针转换为字节数组从mmap得到一个字符串数组指针 - 但是当我看到我看到一些控制字符也许我没有编码字符串字节正确的方式当我' ü冲洗他们通过mmap文件? –

+0

可能控制字符在数据中,可能出现的编码与进入的编码不匹配,并且可能在字节片上进行字符串转换,该字节片在多字节UTF-8的中间开始代码点。 – Adrian