Pergunta

Embora a pesquisa de como fazer isso, eu encontrei uma vaga discussão sobre as diferentes opções, como JNI vs JNA, mas não muito na forma de exemplos concretos.

Contexto: se File.renameTo() de Java não pode fazê-lo de trabalho (por qualquer motivo; é uma pouco problemático ), eu gostaria de cair de volta para usar diretamente esta função nativa do Windows, que é definido no kernel32.dll ( a partir desta resposta ):

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

Assim, usando qualquer abordagem, exatamente como você chamar essa função de dentro do código Java? Eu estou procurando a maneira mais simples, com a quantidade mínima de código ou extra passos não-Java (por exemplo, na compilação ou implantação).

Foi útil?

Solução

Se você vai com ANJ, considere invocação MoveFileW diretamente - isso evita ter de fornecer informações de configuração para escolher entre as chamadas Unicode e 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());
    }
  }
}

EDIT: Eu editei a minha resposta depois de verificar o código - eu estava enganado sobre o uso de char [] na assinatura - é melhor usar wstring .

Outras dicas

Se este for realmente necessário (renameTo não funciona e você está certo MoveFile vai), eu usaria JNA . Parece que a maior parte do trabalho já está feito no com.mucommander.file.util. Kernel32.java / Kernel32API.java .

Com base na biblioteca NativeCall eu fiz o seguinte POC Aplicação .

Ele usa a função MoveFileA de kernel32.dll

Ele vem como exemplo de trabalho completo com uma run.bat e todos jarra e dlls no lugar.

Ele move o incluiu test.txt para test2.txt


Se você não gosta da versão da biblioteca NativeCall eu fiz outra POC Aplicação baseado em / resuing na Java Native Access (JNA) biblioteca. Este MoveFileA tempo e MoveFileW são implementados e demonstrada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top