Question

En cherchant comment faire cela, j’ai trouvé une discussion vague sur différentes options, comme JNI vs JNA, mais pas beaucoup d’exemples concrets.

Contexte: si le File.renameTo () de Java ne peut pas faire son travail (pour une raison quelconque; c'est un peu problématique ), j'aimerais revenir directement à l'utilisation de cette fonction Windows native, définie dans kernel32.dll (de cette réponse ):

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

Alors, quelle que soit l’approche choisie, comment appelleriez-vous cette fonction à partir de code Java? Je recherche le moyen le plus simple, avec un minimum de code non-Java ou d’étapes supplémentaires (par exemple, lors de la compilation ou du déploiement).

Était-ce utile?

La solution

Si vous optez pour la JNA, envisagez d'appeler MoveFileW directement - cela évite de devoir fournir des informations de configuration pour choisir entre les appels Unicode et 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: J'ai modifié ma réponse après avoir vérifié le code - je me suis trompé en utilisant char [] dans la signature - il vaut mieux utiliser WString .

Autres conseils

Si cela est vraiment nécessaire (renameTo ne fonctionne pas et que vous êtes sûr que MoveFile le fera), j'utiliserais JNA . Il semble que la plupart du travail soit déjà effectué dans com.mucommander.file.util. Kernel32.java / Kernel32API.java .

Basé sur la bibliothèque NativeCall , j'ai rédigé ce qui suit Application POC .

Il utilise la fonction MoveFileA de kernel32.dll

Il s'agit d'un échantillon de travail complet avec un fichier run.bat et tous les fichiers jar et dll en place.

Il déplace le fichier test.txt inclus vers test2.txt

Si vous n'aimez pas la version de la bibliothèque NativeCall, j'ai effectué une autre Application POC basée sur la bibliothèque Java Native Access (JNA) . Cette fois, MoveFileA et MoveFileW sont implémentés et démontrés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top