2012-03-27 1 views
6

Sotto Windows, questo codice F # estenderà un file da 12 byte a 65.0346 byte quando l'argomento della capacità (ultimo argomento) è impostato su una dimensione maggiore rispetto al file sottostante. Questo sembra essere il modo più pulito per estendere un file mappato in memoria. Sotto mono/linux genera una ArgumentException: capacità a meno che il file non sia lungo quanto la capacità mappata. C'è un modo pulito per ottenere mono per estendere il file o devo preextend il file prima che posso mappare?MemoryMappedFiles.MemoryMappedFile.CreateFromFile non estenderà un file sotto linux/mono

let Main() = 
    let path = "parts.pash" 
    let l = 65536L 
    let mm = MemoryMappedFiles.MemoryMappedFile.CreateFromFile(path,FileMode.OpenOrCreate,"pashmap",l) 

    () 

Main() 

Messaggio di errore

Eccezione non gestita: System.ArgumentException: capacità a System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile (percorso System.String, modalità FileMode, System.String mapName, Int64 capacità, accesso MemoryMappedFileAccess) [0x00000] in: 0 a System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile (percorso System.String, modalità FileMode, System.String mapName, Int64 capacità) [0x00000] in: 0 a Program.Main() [0x00000] in: 0 a $ Program.main @() [0x00000] in:. 0

versione mono:

[[email protected] pash]$ mono --version 
Mono JIT compiler version 2.10.1 (tarball Mon Apr 4 10:40:52 PDT 2011) 
Copyright (C) 2002-2011 Novell, Inc and Contributors. www.mono-project.com 
     TLS:   __thread 
     SIGSEGV:  altstack 
     Notifications: epoll 
     Architecture: x86 
     Disabled:  none 
     Misc:   softdebug 
     LLVM:   supported, not enabled. 
     GC:   Included Boehm (with typed GC and Parallel Mark) 

EDIT: sembra che il diverso comportamento di fondo di mappatura della memoria è esposta nel API quindi è necessario estendere il file da soli alla lunghezza diritto di essere piattaforma neutrale

let f = File.Open(path,FileMode.Append,FileAccess.Write) 
let pad = l- FileInfo(path).Length 
let padding = Array.create (int32 pad) 0uy 
f.Write(padding,0,int pad) 
f.Close() 

risposta

4

Guardando l'attuazione .NET di CreateFromFile non c'è implementazione di quella funzionalità. A parte il controllo degli argomenti, è un involucro sottile attorno alla chiamata dell'API di Windows da ciò che posso dire.

Per questo motivo la possibilità di creare un file più grande è più di una felice coincidenza dal terreno .NET, quindi non è una sorpresa che Mono abbia rimosso quell'abilità se il sistema operativo sottostante non consente funzionalità simili.

Più semplicemente, non probabile, poiché la versione .NET non estende tecnicamente il file, l'API di Windows.

+0

Sembra una sottile difesa dell'API :) I documenti per la funzione elencano le circostanze in cui un ArgumentException può essere generato e non menzionano l'argomento della capacità. Suppongo che si possa sostenere che il contratto .NET è "qualunque sia il sistema operativo sottostante che si sente di fare", ma questo è un modo scadente per eseguire un'API. – Darren

+0

@Darren: non inteso come una difesa, inteso semplicemente come una dichiarazione di fatto. In genere, i dettagli di implementazione del SO aumentano per necessità di semplicità, questo non è affatto l'ideale per l'utente. – Guvante

+1

@Darren: per peggiorare le cose, l'unico modo affidabile per chiamare il metodo è con la dimensione esatta del file. Windows non consente una dimensione inferiore alla dimensione del file e Mono su UNIX non consente una dimensione maggiore del file. – Guvante

0

Anziché allocare un array potenzialmente grande e quindi scriverlo, è probabilmente più efficiente da cercare. Non sono sicuro del codice F #, ma in C# si farebbe qualcosa di simile:

filestream.Seek(length - 1, SeekOrigin.Begin); 
filestream.WriteByte(0); 

Con Mono 2.10.8 su Mac OS X cerca di per sé non era sufficiente, ho dovuto scrivere almeno un byte, nonostante la documentazione MSDN per FileStream.Seek che dice che estenderà il file.

Sembra che Mono possa fare qualcosa di simile nella sua implementazione MemoryMappedFile per renderlo più compatibile con .Net su Windows.