2009-06-16 15 views
7

यह करने के लिए खोज करते समय, मुझे विभिन्न विकल्पों के बारे में कुछ अस्पष्ट चर्चा मिली, जैसे जेएनआई बनाम जेएनए, लेकिन ठोस उदाहरणों के रास्ते में ज्यादा नहीं।जावा से विंडोज कर्नेल फ़ंक्शन को कॉल करने का सबसे आसान तरीका क्या है?

प्रसंग:;:

अगर जावा के File.renameTo() यह (जो भी कारण के लिए it is a little problematic) काम है ऐसा नहीं कर सकते, मैं वापस सीधे इस देशी विंडोज समारोह है, जो kernel32.dll में परिभाषित किया गया है ( from this answer) का उपयोग करने के लिए गिर करना चाहते हैं
BOOL WINAPI MoveFile(
    __in LPCTSTR lpExistingFileName, 
    __in LPCTSTR lpNewFileName 
); 

तो, जो भी दृष्टिकोण का उपयोग कर, आप जावा फ़ंक्शन के भीतर से उस फ़ंक्शन को वास्तव में कैसे कॉल करेंगे? मैं न्यूनतम मात्रा में गैर-जावा कोड या अतिरिक्त चरणों (जैसे संकलन या तैनाती में) के साथ सबसे आसान तरीका ढूंढ रहा हूं।

उत्तर

7

यदि आप जेएनए के साथ जाते हैं, तो सीधे MoveFileW पर आक्रमण करने पर विचार करें - यह यूनिकोड और एएनएसआई कॉल के बीच चयन करने के लिए कॉन्फ़िगरेशन जानकारी प्रदान करने के लिए बचाता है।

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

संपादित करें: मैं कोड की जाँच के बाद मेरा उत्तर संपादित किया है - मैं हस्ताक्षर में [] चार का उपयोग कर के बारे में गलत था - यह WString उपयोग करने के लिए बेहतर है।

+0

दोनों को कार्यान्वित करना ठीक है, लेकिन * कैसे * MoveFileW को सीधे कॉल करने के लिए कैसे? मैथ्यू फ्लैंचन की तरह सुझाव देता है, या क्या? उदाहरण कोड की कुछ पंक्तियां (जैसे नेटिव.लोड लाइब्रेरी() आदि का उपयोग कैसे करें) की सराहना की जाएगी। – Jonik

+0

क्या आपने मेरा कामकाजी उदाहरण देखा? – jitter

+0

जेएनए उदाहरण के लिए धन्यवाद! बीटीडब्ल्यू, इंटरफ़ेस MoveFileA (जिटर के उत्तर में उल्लिखित) के लिए कैसे देखेंगे? बस "MoveFileW" के बजाय "MoveFileA" का उपयोग करना अच्छा नहीं था। मैं वास्तव में एक निर्देशिका को स्थानांतरित करने/पुनर्नामित करने की कोशिश कर रहा हूं, और यह इस के साथ काम नहीं कर सका - हालांकि मुझे यकीन नहीं है कि यह MoveFileW या किसी और चीज़ के कारण है। – Jonik

1

यदि यह वास्तव में आवश्यक है (नाम बदलना नहीं है और आप निश्चित रूप से MoveFile करेंगे), तो मैं JNA का उपयोग करूंगा। ऐसा लगता है कि अधिकांश काम com.mucommander.file.util में पहले से ही किया जा चुका है। Kernel32.java/Kernel32API.java

+0

और GetLastError() को File.renameTo() – akarnokd

+0

के विपरीत असफल चालों के लिए सार्थक स्पष्टीकरण प्राप्त करने के लिए मत भूलना, मुझे यकीन नहीं है/Move/MoveFile काम करेगा, लेकिन मैं कोशिश कर सकता हूं, नाम बदलने के लिए निश्चित रूप से नहीं है। बीटीडब्ल्यू, आप जिन दो फाइलों को लिंक करते हैं वे पूरी तरह फिट नहीं होते हैं; कर्नेल 32API.DEFAULT_OPTIONS गुम है। आपको Native.loadLibrary को तीसरे पैरामीटर के रूप में क्या पास करना चाहिए? मैं खाली नक्शा के साथ कोशिश कर रहा हूं और इसे काम पर नहीं ला सकता; "क्लासकास्ट अपवाद: $ प्रॉक्सी 0 com.sun.jna.Library को नहीं डाला जा सकता" होता है। – Jonik

+0

क्या आपने मेरा उदाहरण आजमाया? – jitter

1

NativeCall library के आधार पर मैंने निम्नलिखित POC Application पर आधारित किया।

यह kernel32.dll

से MoveFileA फ़ंक्शन का उपयोग करता यह एक run.bat और सभी जार और जगह में DLLs के साथ के रूप में पूरा काम कर नमूना आता है।

इसमें शामिल थे test.txt test2.txt को


आप मुझे एक और POC Application के आधार पर/Java Native Access (JNA) पुस्तकालय पर resuing किया NativeCall पुस्तकालय संस्करण पसंद नहीं है ले जाता है। इस बार MoveFileA और MoveFileW लागू और प्रदर्शित किए गए हैं।

+0

धन्यवाद! नेटिवॉल का उपयोग करके मैं जावा से बड़ी निर्देशिकाओं के लिए त्वरित कदम करने में सक्षम था (हालांकि मैंने अभी तक उस स्थिति में कोशिश नहीं की है जहां नाम बदलना अक्सर विफल रहता है), और कॉल करने के लिए कोड वास्तव में सरल है। लेकिन अब मुझे नेटिवॉल के बारे में कुछ संदेह हैं।डीएलएल फ़ाइल - अगर आपको हमेशा काम करने वाले डीआईआर में रखना है तो यह बेकार लगता है (यदि यह एक जार के अंदर था, तो एपीआई के उपयोगकर्ता के लिए पारदर्शी रूप से उपयोग किया जाता था, lib को एम्बेड करना आसान होगा) – Jonik

+0

जैसा कि आप पसंद नहीं करते नेटिवॉल संस्करण मैंने जेएनए पीओसी ऐप भी किया था। MoveFileA और MoveFileW – jitter

संबंधित मुद्दे

 संबंधित मुद्दे