2017-06-13 16 views
0

私は安全でないパッケージのエキスパートではありません - 私は熟練したCプログラマーではありません。私は巨大なファイル> 1Gをmmapシステムコールを使って読み込もうとしています。 I/Oを読み書きするのではなく、mmapとmunmapを行う理由はいくつかあります。それはポイントの横にある - 私はテストでファイルに書き込むことができます、私はファイルから読むと、私はバイトの長さが一致することを確認することができますが、私はこの文字列ファイルの内容を読み取ることができません:さらに少し行くために行う必要があり、ここで私は、サンプルテスト用に調理されたいくつかのコードです:mmap syscall読み込み用に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ファイル上のmmap()を経由して、どのように行うを読みたい場合どのような私はこれらのバイトから文字列を読んでいます(私はおそらく、おそらく使用するために置かなければならないかもしれないエンコーディングパッケージがありますが、安全でないドキュメントのStringHeaderは私を混乱させます)。

+0

おそらく私はあなたが何を意味するか得ることはありません。 'mmap'を使用している場合、ファイルの内容は' [] byte'として利用できませんか?文字列を取得するには、 'string(mmap [:100])' '< - 最初の100バイトを文字列に変換します。または、['bytes.Buffer'](https://golang.org/pkg/bytes/#Buffer)を使うことができます(io.reader/io.writerパターンを避けているので、おそらくあなたが望むものではありません)。 – putu

+0

I読者を避けたい - しかし、私の問題は、文字列をmmap経由でバイトに書き込んでいる間に、正当なcharsをちょうどいくつかの制御文字にするのではないかと思われます。 –

+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

関連する問題