java中URL和File的相互转化 及两者的使用场景

  1. 首先,想比较一下这两者的不同。
  2. URL用于网络,所以带有明显的protocol,而且对于中文及符号支持的很不好。
  3. File就是我们平常系统中的文件路径了,对于中文及符号都支持,但是已经没有protocol了。所以,虽然两者都可以表示文件路径,但是却不能混用了。  

  4. 典型的URL和File路径的比较:  
  5. URL:file:/D:/my%20java/URL&FILE/%e5%9b%be%e7%89%87/tongji.jpg  
  6. File:D:/my java/URL&FILE/图片/tongji.jpg  
  7. 其实两者是一个文件。  
  8.   
  9. 回到正题:  
  10. 这是我在JDK5.0下找到的方法,JDK5.0以下不支持:  
  11. URL to File:  
  12. URL url=……;  
  13. File file=new File(url.toURI);  
  14.   
  15. File to URL:  
  16. File file=……;  
  17. URL url=file.toURL();  
  18.   
  19.    
  20.   
  21. ++++++++++++++++++++++++++++  
  22.   
  23. 获取JAVA路径,包括CLASSPATH外的路径  
  24.   
  25. 归纳一些网上取JAVA路径的方法:  
  26.   注明:如果从ANT启动程序,this.getClass().getResource("")取出来的比较怪,直接用JAVA命令行调试就可成功。  
  27.     
  28.   得到classpath和当前类的绝对路径的一些方法  
  29.   获得CLASSPATH之外路径的方法:  
  30.   URL base = this.getClass().getResource(""); //先获得本类的所在位置,如/home/popeye/testjava/build/classes/net/  
  31.   String path = new File(base.getFile(), "../../../"+name).getCanonicalPath(); //就可以得到/home/popeye/testjava/name  
  32.   下面是一些得到classpath和当前类的绝对路径的一些方法。你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。  
  33.   1.FileTest.class.getResource("")  
  34.   得到的是当前类FileTest.class文件的URI目录。不包括自己!  
  35.   如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/com/test/  
  36.   2.FileTest.class.getResource("/")  
  37.   得到的是当前的classpath的绝对URI路径。  
  38.   如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/  
  39.   3.Thread.currentThread().getContextClassLoader().getResource("")  
  40.   得到的也是当前ClassPath的绝对URI路径。  
  41.   如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/  
  42.   4.FileTest.class.getClassLoader().getResource("")  
  43.   得到的也是当前ClassPath的绝对URI路径。  
  44.   如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/  
  45.   5.ClassLoader.getSystemResource("")  
  46.   得到的也是当前ClassPath的绝对URI路径。  
  47.   如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/  
  48.     
  49. 我推荐使用Thread.currentThread().getContextClassLoader().getResource("")来得到当前的classpath的绝对路径的URI表示法。  
  50.   在Web应用程序中,我们一般通过ServletContext.getRealPath("/")方法得到Web应用程序的根目录的绝对路径。这样,我们只需要提供相对于Web应用程序根目录的路径,就可以构建出定位资源的绝对路径。  
  51.   注意点:  
  52.   1.尽量不要使用相对于System.getProperty("user.dir")当前用户目录的相对路径。这是一颗定时炸弹,随时可能要你的命。  
  53.   2.尽量使用URI形式的绝对路径资源。它可以很容易的转变为URI,URL,File对象。  
  54.   3.尽量使用相对classpath的相对路径。不要使用绝对路径。使用上面ClassLoaderUtil类的public static URL getExtendResource(String relativePath)方法已经能够使用相对于classpath的相对路径定位所有位置的资源。  
  55.   4.绝对不要使用硬编码的绝对路径。因为,我们完全可以使用ClassLoader类的getResource("")方法得到当前classpath的绝对路径。  
  56.   使用硬编码的绝对路径是完全没有必要的!它一定会让你死的很难看!程序将无法移植!  
  57.   如果你一定要指定一个绝对路径,那么使用配置文件,也比硬编码要好得多!  
  58.   当然,我还是推荐你使用程序得到classpath的绝对路径来拼资源的绝对路径。  
  59.   
  60. =============================================================================  
  61.   
  62. 在开发java程序的过程中,我们经常要做的一件事就是获取资源。那么什么是资源呢?说白了,在计算机里那就是一堆数据。只是这堆数据对我们的java程序有多种表现形式,一般来说有File,URL,InputStream等等。而单就文件这一项就有很多种:配置文件,java类文件,jps文件,图片、css、js文件等等。面对这林林总总的资源,我们在设计一个读取资源的接口时,就需要针对不同形式的资源提供方法,这样就导致我们的接口还是与实际的资源形式绑定在一起,未能完全的抽象。另外,在java程序中资源的存放位置也是各异的。有的存放在classpath中,有的存放在文件系统中,有的存放在web应用中。而对于不同位置的资源,java程序获取这些资源的方法各有不同。   
  63. A、获取classpath中的资源:   
  64. Java代码   
  65. URL url = this.getClass().getResource("resource_name");    
  66. URL url = this.getClass().getClassLoader().getResource("resource_name");    
  67. URL url = Thread.currentThread().getContextClassLoader().getResource("resource_name");    
  68.   
  69. 那么在jdk中为什么又提供了三种方式来获取classpath下的资源呢?这其中是有些来头的。   
  70. 第一行代码中是利用Class类的实例来获取,第二行代码是使用加载当前类的classloader来获取。看下jdk中的源代码会发现class类的实例最后还是委托加载他的classloader来获取资源的。   
  71. Java代码   
  72. public java.net.URL getResource(String name) {    
  73.     name = resolveName(name);    
  74.     ClassLoader cl = getClassLoader0();    
  75.     if (cl==null) {    
  76.         // A system class.    
  77.         return ClassLoader.getSystemResource(name);    
  78.     }    
  79.     return cl.getResource(name);    
  80. }    
  81.   
  82. 从上面的代码中可以看出,对于资源的加载并没有像类加载所采用的双亲委托机制。而是当前类的classloader不为null的情况下先从当前类的classloader中加载资源。而只有当前类的classloader为null的时候才从system classloader中去加载资源。这样可以方便我们自定义配置类覆盖一些默认配置。当然,j2se应用中如果没有特别定制classloader时,我们自己写的类都是被system classloader加载的。到底利用class去获取资源和利用classloader去获取资源有什么区别呢?区别就在 resolveName(name)这个方法中。两种方式对于资源名称的表示方式不同。下面是一个简单的包结构,/表示类路径的根   
  83. /   
  84. |-com.cn.test   
  85.    |-Test.class   
  86.    |-test2.txt    
  87. |-test1.txt   
  88. Java代码   
  89. // 获取与当前类在同一个包下的资源    
  90. URL url1 = this.getClass().getResource("test2.txt");    
  91. // 获取com.cn.test包下的资源,需加/    
  92. URL url2 = this.getClass().getResource("/com/cn/test/test2.txt");    
  93. // 获取类路径根下的资源    
  94. URL url3 = this.getClass().getClassLoader().getResource("test1.txt");    
  95. // 获取包com.cn.test包下的资源    
  96. URL url4 = this.getClass().getResource("com/cn/test/test2.txt");    
  97.   
  98. 而第三利用当前线程的contextClassLoader来获取资源的解释可以参考我的另一篇   

  99. B、获取文件系统中的资源   
  100. Java代码   
  101. // 1、获得File对象    
  102. File file = new File("test.txt");    
  103. // 2、获得File对象的字节流    
  104. InputStream in = new FileInputStream(file);    
  105.   
  106. 值得注意的是在File的构造函数File(String name) 中的name参数可以是相对路径和绝对路径。相对路径是相对于System.getProperties("user.dir")的。  
  107. C、获取web应用中的资源   
  108. Java代码   
  109. servletContext.getResourceAsStream(resource_name);    
  110.   
  111. resource_names为相对于webroot的路径表示。例如获取web.xml,resource_name表示为"/WEB-INF/web.xml"   
  112.   
  113.     面对上面介绍的各种资源表现形式和存放位置,难道java中就没有提供一个统一处理方式吗?有,java.net.URL。   
  114. 从名称上来看 URL(Uniform Resource Locator) 统一资源定位器。看起来很好很强大。但很多时候使用它并不能定位到我们需要的资源。   
  115.     首先,它jdk中体统的URL能访问的协议非常有限(当然可以进行扩展,不过很麻烦);常用的有http,file,ftp等等。并没有提供对classpath和servletContext中的资源的获取方法。   
  116.     另外,它没有提供判断资源是否存在的方法。每次只有等我们真正去获取资源的时候抛出异常才能知道资源无法获取。   
  117.     其次,URL这个类的职责未划分清楚,既用来表示资源有用来获取其资源。   
<think>首先,用户的问题集中在Android Java开发中集成JavaScript代码执行,并实现Java与JNI的互相调用。我需要参考提供的引用内容来构建回答。 关键引用点: - 引用[1]:讨论了在Java中执行JavaScript,使用ScriptEngine类。这适用于在Java环境中运行JavaScript。 - 引用[2][3]:涉及JNI(Java Native Interface),允许Java与本地代码(如C/C++)交互。 - 引用[4]:提供了JNI中字符串处理的例子。 - 引用[5]:提到了Android项目结构,包括jni文件夹的创建。 用户需求分解: 1. 在Android Java中执行JavaScript代码。 2. 实现Java与JNI的交互调用。 回答结构: - 由于用户要求结构清晰,逐步解决问题,我需要分步解释。 - 使用中文回答。 - 确保LaTeX语法正确:行内数学表达式用$...$,独立公式用$$...$$并单独成段。 - 生成相关问题。 步骤: 1. **执行JavaScript代码**:使用Android的WebView或ScriptEngine。引用[1]提到ScriptEngine,但Android支持可能有限;WebView更常用。 2. **Java与JNI交互**:设置JNI环境,编写本地方法,处理调用。 3. **整合两者**:可能需要在JNI中调用JavaScript,或反之,但这不直接;可能需要通过Java层桥接。 详细回答: - **第一步:在Android中执行JavaScript** - 推荐使用WebView来执行JavaScript,因为Android的ScriptEngine(如Rhino)在较新版本中可能不默认支持或已被弃用。 - 示例:在WebView中加载HTML并执行JS。 - 代码示例:展示如何在Java中调用WebView的evaluateJavascript方法。 - **第二步:实现Java与JNI交互** - 设置NDK(Native Development Kit)环境。 - 创建jni文件夹,编写C/C++代码。 - 定义本地方法,使用JNI接口。 - 示例:从Java调用本地方法,本地方法返回结果。 - 引用[4][5]提供线索:jni.h的使用,字符串转换。 - **整合:在JNI中涉及JavaScript** - 这更复杂。JNI直接与JavaScript交互不直接;需要通过Java层。例如,在JNI本地代码中回调Java方法,Java方法再执行JavaScript。 - 或者,使用混合方法:WebView执行JS,然后通过接口与Java通信。 确保真实性: - 基于Android开发最佳实践:WebView for JS, NDK for JNI. - 参考引用:引用[1]的ScriptEngine可能不适用于Android;更推荐WebView。引用[2]-[5]支持JNI部分。 LaTeX格式: - 如果有数学表达式,如方程,使用$...$。例如,讨论性能时可能有公式。 - 在这个上下文中,可能没有太多数学,但如果有,需正确格式。 生成相关问题: - 在回答末尾,添加相关问题,如示例所示。 完整回答结构: 1. 介绍:简要说明需求。 2. 执行JavaScript部分:解释代码。 3. JNI交互部分:解释代码。 4. 整合建议:如何使它们协同工作。 5. 总结。 6. 相关问题。 代码示例: - 使用Markdown代码块,如示例中的Python代码。 - 提供Java可能的C++代码。 引用标识: - 在相关部分末尾添加[^n],但引用是给定的;我需要参考它们。 - 例如,提到ScriptEngine时引用[^1],JNI时引用[^2],[^3]等。 最终输出: - 以用户可见层开始。 - 确保回答可靠:基于标准Android开发实践。</think>### Android Java开发中集成JavaScript执行与Java-JNI交互调用指南 在Android开发中,集成JavaScript代码执行并实现Java与JNI(Java Native Interface)的交互调用,可以提升应用功能灵活性(如动态脚本处理)性能(如本地代码优化)。以下是基于Android标准实践的分步解决方案,确保真实可靠。参考引用内容,我将从JavaScript执行开始,逐步过渡到JNI交互,最后讨论整合方法。整个过程需Android StudioNDK(Native Development Kit)支持。 --- ### 第一步:在Android中执行JavaScript代码 Android中执行JavaScript通常通过`WebView`组件实现,因为它内置了JavaScript引擎(如V8)。`ScriptEngine`(引用自Rhino引擎)在标准Android中不推荐使用,因为它未被官方全面支持且在高版本Android中可能受限[^1]。以下是推荐方法: 1. **使用WebView执行JavaScript**: - 创建`WebView`实例,启用JavaScript,并通过`evaluateJavascript()`方法执行脚本。 - 示例代码(Java): ```java import android.webkit.WebView; import android.webkit.WebViewClient; import android.webkit.WebChromeClient; public class MainActivity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); // 启用JavaScript webView.setWebChromeClient(new WebChromeClient()); // 支持JS弹窗 webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { // 执行JavaScript代码 webView.evaluateJavascript( "javascript:function add(a,b){return a+b;}; add(2,3);", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { Log.d("JS Result", "Result: " + value); // 输出结果,例如:5 } } ); } }); webView.loadData("<html><body></body></html>", "text/html", "UTF-8"); // 加载空页面以执行JS } } ``` - **说明**: - `evaluateJavascript()` 异步执行JS并返回结果(JSON格式)。 - 此方法安全高效,适用于大多数场景,如动态计算或UI交互。 - 引用[1]中提到的`ScriptEngine`在Android中不适用,建议优先使用WebView[^1]。 2. **高级场景JavaScript与Java互调**: - 通过`@JavascriptInterface`注解,允许JavaScript调用Java方法。 ```java webView.addJavascriptInterface(new Object() { @JavascriptInterface public void showToast(String message) { Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show(); } }, "AndroidBridge"); // "AndroidBridge" 是JS中访问的对象名 ``` - 在JavaScript中:`AndroidBridge.showToast("Hello from JS!");` - **注意事项**:Android 4.2+需显式添加`@JavascriptInterface`以避免安全漏洞。 --- ### 第二步:实现Java与JNI交互调用 JNI允许Java代码与本地代码(C/C++)交互,常用于性能敏感操作(如图像处理)。引用[2]-[5]详述了JNI原理Android集成步骤[^2][^3][^4][^5]。以下是标准流程: 1. **设置NDK环境**: - 在Android Studio中,安装NDKCMake:File > Settings > Appearance & Behavior > System Settings > Android SDK > SDK Tools. - 创建`jni`文件夹:在`app/src/main`下新建`jni`目录,存放C/C++文件(引用[5])[^5]。 2. **编写JNI交互代码**: - **步骤1:定义本地方法**(Java层): ```java public class NativeLib { static { System.loadLibrary("native-lib"); // 加载本地库 } public native String callNativeMethod(String input); // 本地方法声明 } ``` - **步骤2:生成JNI头文件**: - Build > Make Project,生成`.class`文件。 - 使用`javac``javah`生成头文件(或Android Studio自动处理): ```bash javac app/src/main/java/com/example/NativeLib.java javah -jni com.example.NativeLib ``` - 输出头文件如`com_example_NativeLib.h`,包含函数签名:`JNIEXPORT jstring JNICALL Java_com_example_NativeLib_callNativeMethod(JNIEnv *, jobject, jstring);` - **步骤3:实现C/C++代码**(在`jni`文件夹): - 文件:`native-lib.cpp` ```cpp #include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_example_NativeLib_callNativeMethod(JNIEnv *env, jobject /* this */, jstring input) { const char *nativeString = env->GetStringUTFChars(input, nullptr); // 转换Java字符串到C字符串 // 示例处理:字符串反转 std::string result = "Processed: " + std::string(nativeString); env->ReleaseStringUTFChars(input, nativeString); // 释放资源 return env->NewStringUTF(result.c_str()); // 返回Java字符串 } ``` - **引用[4]的字符串处理**:使用`GetStringUTFChars``NewStringUTF`处理编码转换[^4]。 3. **配置构建脚本**: - 在`app/build.gradle`中添加NDK支持: ```groovy android { defaultConfig { externalNativeBuild { cmake { cppFlags "-std=c++11" } } } externalNativeBuild { cmake { path "src/main/jni/CMakeLists.txt" } } } ``` - 创建`CMakeLists.txt`(在`jni`文件夹): ```cmake cmake_minimum_required(VERSION 3.4.1) add_library(native-lib SHARED native-lib.cpp) find_library(log-lib log) target_link_libraries(native-lib ${log-lib}) ``` 4. **测试调用**: ```java NativeLib lib = new NativeLib(); String output = lib.callNativeMethod("Hello JNI"); // 输出:"Processed: Hello JNI" ``` --- ### 第三步:整合JavaScript执行与JNI交互 实现JavaScript与JNI的直接调用较复杂,因为WebView(JS环境)JNI(本地环境)隔离。推荐通过Java层桥接: - **方案1:JavaScript → Java → JNI** - JavaScript调用Java方法(通过`@JavascriptInterface`)。 - Java方法调用JNI本地函数。 - 示例流程: - JS: `AndroidBridge.callNative("data")` → Java: `callNative()` 方法中调用 `NativeLib.callNativeMethod()` → JNI: 执行C++代码。 - **方案2:JNI → JavaJavaScript** - JNI本地代码回调Java方法。 - Java方法通过WebView执行JavaScript(如`evaluateJavascript()`)。 - 示例:JNI处理完成后,调用Java回调方法,该方法触发JS更新UI。 **性能与安全考虑**: - **性能**:JNI适合CPU密集型任务,但跨语言调用有开销。WebView执行JS轻量但受限于UI线程。 - **安全**:WebView需防范XSS攻击;JNI需处理内存泄漏(如引用[4]的字符串资源释放)[^4]。 - **统计指标**:跨语言调用延迟可建模为$L = t_{js} + t_{jni}$,其中$t_{js}$是JS执行时间(约1-10ms),$t_{jni}$是JNI调用时间(约0.1-1ms)。 --- ### 总结 在Android中: - 使用**WebView**执行JavaScript,支持双向Java-JS通信。 - 通过**NDK/JNI**实现Java与本地代码交互,需配置`jni`文件夹CMake。 - 整合时,**以Java层为中介**确保兼容性。整个过程需测试不同Android版本(API 21+)。 如需深入优化,可参考Android NDK文档或开源库如LuaJ(引用[2])[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值