7

在寻找如何做到这一点时,我发现了一些关于不同选项的模糊讨论,比如 JNI 与 JNA,但具体示例不多。

上下文:如果 JavaFile.renameTo()不能完成它的工作(无论出于何种原因;它有点问题),我想直接使用这个在 kernel32.dll 中定义的本机 Windows 函数(来自这个答案):

BOOL WINAPI MoveFile(
  __in  LPCTSTR lpExistingFileName,
  __in  LPCTSTR lpNewFileName
);

那么,无论使用哪种方法,您将如何从 Java 代码中调用该函数呢?我正在寻找最简单的方法,使用最少的非 Java 代码或额外的步骤(例如在编译或部署中)。

4

3 回答 3

7

如果您使用 JNA,请考虑直接调用MoveFileW - 它不必提供配置信息以在 Unicode 和 ANSI 调用之间进行选择。

import java.io.*;
import com.sun.jna.*;

public class Ren {

  static interface Kernel32 extends Library {
    public static Kernel32 INSTANCE = (Kernel32) Native
        .loadLibrary("Kernel32", Kernel32.class);

    public static int FORMAT_MESSAGE_FROM_SYSTEM = 4096;
    public static int FORMAT_MESSAGE_IGNORE_INSERTS = 512;

    public boolean MoveFileW(WString lpExistingFileName,
        WString lpNewFileName);

    public int GetLastError();

    public int FormatMessageW(int dwFlags,
        Pointer lpSource, int dwMessageId,
        int dwLanguageId, char[] lpBuffer, int nSize,
        Pointer Arguments);
  }

  public static String getLastError() {
    int dwMessageId = Kernel32.INSTANCE.GetLastError();
    char[] lpBuffer = new char[1024];
    int lenW = Kernel32.INSTANCE.FormatMessageW(
        Kernel32.FORMAT_MESSAGE_FROM_SYSTEM
            | Kernel32.FORMAT_MESSAGE_IGNORE_INSERTS, null,
        dwMessageId, 0, lpBuffer, lpBuffer.length, null);
    return new String(lpBuffer, 0, lenW);
  }

  public static void main(String[] args) throws IOException {
    String from = ".\\from.txt";
    String to = ".\\to.txt";
    new FileOutputStream(from).close();
    if (!Kernel32.INSTANCE.MoveFileW(new WString(from),
        new WString(to))) {
      throw new IOException(getLastError());
    }
  }
}

编辑:我在检查代码后编辑了我的答案 - 我误认为在签名中使用 char[] - 最好使用WString

于 2009-06-16T11:50:20.287 回答
1

如果这确实是必要的( renameTo 不起作用并且您确定 MoveFile 会),我会使用JNA。看起来大部分工作已经在 com.mucommander.file.util 中完成。内核32.java/内核32API.java 。

于 2009-06-16T10:47:23.817 回答
1

基于NativeCall 库,我做了以下POC Application

它使用kernel32.dllMoveFileA中的函数

它作为完整的工作示例提供,带有 run.bat 和所有 jar 和 dll。

它将包含的 test.txt 移动到 test2.txt


如果您不喜欢 NativeCall 库版本,我基于Java Native Access (JNA)库创建了另一个POC 应用程序。这一次并被实施和演示。MoveFileAMoveFileW

于 2009-06-16T11:37:14.977 回答