2012-03-27 7 views
6

En Windows, este código F # extenderá un archivo de, por ejemplo, 12 bytes a 655346 bytes cuando el argumento de capacidad (último argumento) se establece en un tamaño mayor que el archivo subyacente. Esta parece ser la forma más limpia de extender un archivo mapeado en memoria. Bajo mono/linux arroja una ArgumentException: capacity a menos que el archivo sea tan largo como la capacidad mapeada. ¿Hay alguna manera limpia de obtener mono para extender el archivo o tengo que preextender el archivo antes de poder mapear?MemoryMappedFiles.MemoryMappedFile.CreateFromFile no extenderá un archivo en linux/mono

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

    () 

Main() 

mensaje de error

Excepción no controlada: System.ArgumentException: capacidad en System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile (camino System.String, modo FileMode, System.String mapName, Int64 capacidad, acceso MemoryMappedFileAccess) [0x00000] en: 0 a System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile (camino System.String, modo FileMode, System.String mapName, Int64 capacidad) [0x00000] en: 0 a Program.Main() [0x00000] en: 0 a $ Program.main @() [0x00000] en:. 0

Versión del 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: parece que el diferente comportamiento subyacente de asignación de memoria se expone en el API por lo que necesita para ampliar el archivo usted mismo a la longitud adecuada para ser plataforma neutral

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() 

Respuesta

4

en cuanto a la aplicación de .NET CreateFromFile no hay implementación de esa funcionalidad. Aparte de la comprobación de argumentos, es una envoltura delgada alrededor de la llamada API de Windows por lo que puedo decir.

Por esta razón, la capacidad de crear un archivo más grande es más una feliz coincidencia de .NET land, por lo que no sorprende que Mono haya eliminado esa capacidad si el sistema operativo subyacente no permite una funcionalidad similar.

En pocas palabras, no es probable, ya que la versión de .NET tampoco extiende técnicamente el archivo, sí lo hace la API de Windows.

+0

Parece una pequeña defensa de la API :) Los documentos de la función enumeran las circunstancias bajo las cuales se puede generar una ArgumentException y no mencionan el argumento de capacidad. Supongo que podría argumentar que el contrato de .NET es "lo que sea que el sistema operativo subyacente sienta que hace", pero esa es una forma pobre de ejecutar una API. – Darren

+0

@Darren: No se entiende como una defensa, solo se entiende como una declaración de hecho. Normalmente, los detalles de implementación del SO surgen por necesidad de simplicidad, esto de ninguna manera es ideal para el usuario. – Guvante

+1

@Darren: Para empeorar las cosas, la única manera confiable de llamar al método es con el tamaño exacto del archivo. Windows no permite un tamaño inferior al del archivo y Mono en UNIX no permite un tamaño superior al del archivo. – Guvante

0

En lugar de asignar una matriz potencialmente grande y luego escribirla, probablemente sea más eficiente buscarla. No estoy seguro del # código F, pero en C# que haría algo como:

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

Con Mono 2.10.8 en Mac OS X que buscan por sí sola no era suficiente, que tenía que escribir al menos una byte, a pesar de la documentación de MSDN para FileStream.Seek diciendo que ampliará el archivo.

Parece que Mono podría hacer algo similar en su implementación de MemoryMappedFile para hacerlo más compatible con .Net en Windows.

Cuestiones relacionadas