【问题标题】:Read C#'s MemoryMappedFile in Java在 Java 中读取 C# 的 MemoryMappedFile
【发布时间】:2022-01-01 01:46:42
【问题描述】:

你好,新年快乐!

如果可能的话,我一直在寻找用 Java/Kotlin 编写这段代码的方法......

MemoryMappedFile memfile = MemoryMappedFile.OpenExisting("MAHMSharedMemory");
BinaryReader br = new BinaryReader(memfile.CreateViewStream());
br.BaseStream.Seek(0, SeekOrigin.Begin);

OpenExisting 的文档指出:

在系统内存中打开具有指定名称的现有内存映射文件。

CreateViewStream 的文档告诉我:

创建一个映射到内存映射文件视图的流。

这两种方法的 Java/Kotlin 等价物是什么?

【问题讨论】:

  • Java 没有像这样打开命名共享内存的本地方式。 Java 内存映射文件(通过FileChannel 类)需要由磁盘上的文件支持。如果你真的需要使用命名共享内存,你可以使用 JNI 来做到这一点,正如 in this answer 解释的那样,但实际上,既然你将使用 Windows 特定的功能,为什么还要使用 Java?
  • 我明白了!选择 Java 是因为它是我最熟悉的语言,我想用 Kotlin 做一个简单的 jetpack compose 桌面应用程序

标签: java c# java-io


【解决方案1】:

正如@Etienne de Martel 所提到的,如果没有 JNA 或 JNI 的任何帮助,我们无法直接从 Java 中读取它......幸运的是,SO 上还有另一个 thread 为我指明了正确的方向...... .

我需要做的是:

public interface Kernel32Impl extends com.sun.jna.platform.win32.Kernel32 {
    Kernel32Impl KERNEL_32 = Native.load("kernel32", Kernel32Impl.class, W32APIOptions.DEFAULT_OPTIONS);
    HANDLE OpenFileMapping(int lfProtect, boolean bInherit, String lpName);
    HANDLE OpenEvent(int i, boolean bManualReset, String lpName);
}

最后在 Kotlin 中

class WindowsService {

    var lastError: Int = 0
        private set

    fun openMemoryMapFile(filename: String): WinNT.HANDLE? {
        val memMapFile = Kernel32Impl.KERNEL_32.OpenFileMapping(WinNT.SECTION_MAP_READ, false, filename)
        lastError = Kernel32Impl.KERNEL_32.GetLastError()

        return memMapFile
    }

    fun closeHandle(handle: WinNT.HANDLE) {
        Kernel32Impl.KERNEL_32.CloseHandle(handle)
    }

    fun mapViewOfFile(handle: WinNT.HANDLE?): Pointer? {
        handle ?: return null

        return Kernel32.INSTANCE.MapViewOfFile(handle, WinNT.SECTION_MAP_READ, 0, 0, 0)
    }

    fun unmapViewOfFile(pointer: Pointer) {
        Kernel32Impl.KERNEL_32.UnmapViewOfFile(pointer)
        lastError = Kernel32Impl.INSTANCE.GetLastError()
    }
}

然后是那个的实际用法:

windowsService.openMemoryMapFile(MEMORY_MAP_FILE_NAME)?.let { handle ->
            windowsService.mapViewOfFile(handle)?.let { pointer ->
                val buffer = ByteBuffer.allocateDirect(BLOCK_SIZE)
                buffer.put(pointer.getByteArray(0, BLOCK_SIZE))
                buffer.order(ByteOrder.LITTLE_ENDIAN)
                buffer.rewind()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    相关资源
    最近更新 更多