java在运行时能修改工作目录吗

 更新时间:2019年08月07日 11:03:46   作者:lost陆离  
这篇文章主要给大家介绍了关于java在运行时能修改工作目录的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

首先我们直接来看一个例子:

程序启动目录即工作目录是/Users/qkkcoolmax/work-private/testuserdir/hehe

public static void main(String[] args) {
  File file = new File("haha/test.log");
  System.out.println(file.getAbsolutePath());
  //Users/qkkcoolmax/work-private/testuserdir/hehe/haha/test.log
  System.out.println(System.setProperty("user.dir", "/Users/qkkcoolmax/work-private/testuserdir"));
  //Users/qkkcoolmax/work-private/testuserdir/hehe
  System.out.println(System.getProperty("user.dir"));
  //Users/qkkcoolmax/work-private/testuserdir
  System.out.println(file.getAbsolutePath());
  //Users/qkkcoolmax/work-private/testuserdir/haha/test.log
  try {
   new FileOutputStream(file);
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }
 }

该程序会抛FileNotFoundException异常。这是由于File对象使用了相对路径创建,虽然我们动态修改了System.proproties中的user.dir即修改了java层面的工作目录,但并没有修改到jvm中实际记录的工作目录,所以需要创建的文件路径中hehe/haha目录并不存在,从而抛异常。其实System.property只是修改了System中的一个静态map变量。

而getAbsolutePath返回的是修改工作目录后的文件路径,这是由于getAbsolutePath中总是会用System.getProperty("user.dir")来和相对路径拼接,得到absolutePath。

综上,我们了解到System.setProperty("user.dir",newPath)的方式是无法修改进程实际的工作目录的,这个值是存放在jvm底层数据结构中。但是有些特殊场景,我们确实希望能动态修改一下工作目录。譬如一个服务端进程需要处理不同目录下的文件,历史代码或者框架中使用了一些相对路径,我们难以替换成绝对路径时,动态修改工作目录就成了唯一实现目标的途径。

所以,java是否可以动态修改工作目录呢? 先说结论,是可以的!

首先,java语言层面并没有提供这样的接口。

其次,我们知道在c语言中,可以很方便的调用chdir系统调用来切换当前进程的工作目录。那么只要java能调用到jvm中链进来的libc中的chdir不就好了么。

java调c有几种方式呢?有一定经验的读者可能马上会想到JNI。实际上,我们可以采用更好的方式即JNA。JNA(Java Native Access )提供一组Java工具类用于在运行期间动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。

简单来说,JNA可以让java代码直接调用c代码(包括jvm里面的代码),使用方式相比jni更加简单方便。

对JNA的介绍网上资料还蛮丰富的,感兴趣的读者可以自行搜索研究。这里我们直接使用了jnr-posixz(https://github.com/jnr/jnr-posixz)。该库已经对不同平台的JNA调用实现了良好的封装,避免我们使用原生的JNA时处理各种跨平台的逻辑。

引入依赖

<dependency>
 <groupId>com.github.jnr</groupId>
 <artifactId>jnr-posix</artifactId>
 <version>3.0.47</version>
</dependency>  

使用示例

public class Main {

 private static POSIX posix;

 public static void main(String[] args) {
  posix = POSIXFactory.getPOSIX(new DummyPOSIXHandler(), true);
  File file = new File("haha/test.log");
  System.out.println(file.getAbsolutePath());
  //Users/qkkcoolmax/work-private/testuserdir/hehe/haha/test.log
  System.out.println(System.setProperty("user.dir", "/Users/qkkcoolmax/work-private/testuserdir"));
  posix.chdir(System.getProperty("user.dir"));
  //Users/qkkcoolmax/work-private/testuserdir/hehe
  System.out.println(System.getProperty("user.dir"));
  //Users/qkkcoolmax/work-private/testuserdir
  System.out.println(file.getAbsolutePath());
  //Users/qkkcoolmax/work-private/testuserdir/haha/test.log
  try {
   new FileOutputStream(file);
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }
 }
}

run起来,能够成功创建出 /Users/qkkcoolmax/work-private/testuserdir/haha/test.log文件,无任何异常。

好了,动态修改java工作目录达成,请自行取用。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • 解决SpringBoot2多线程无法注入的问题

    解决SpringBoot2多线程无法注入的问题

    这篇文章主要介绍了解决SpringBoot2多线程无法注入的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java输出链表倒数第k个节点

    Java输出链表倒数第k个节点

    这篇文章主要介绍了Java输出链表倒数第k个节点的相关内容,涉及三种设计思路及代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • SpringBoot中swagger的使用

    SpringBoot中swagger的使用

    这篇文章主要介绍了SpringBoot中swagger的使用,文中有非常详细的代码示例,对正在学习swagger的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-05-05
  • java实现发送email小案例

    java实现发送email小案例

    这篇文章主要为大家详细介绍了java实现发送email小案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • Java IO流之节点流与字符流的相关知识总结

    Java IO流之节点流与字符流的相关知识总结

    今天给大家带来的是关于Java的相关知识,文章围绕着Java节点流与字符流展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • SpringBoot 回滚操作的几种实现方式

    SpringBoot 回滚操作的几种实现方式

    回滚操作是一种常见的操作,用于撤销之前执行的操作,本文主要介绍了SpringBoot回滚操作的几种实现方式,包含基于异常类型的回滚、基于自定义逻辑的回滚和基于数据库状态的回滚,感兴趣的可以了解一下
    2024-03-03
  • 简单了解Spring循环依赖解决过程

    简单了解Spring循环依赖解决过程

    这篇文章主要介绍了简单了解Spring循环依赖解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • SpringBoot Starter依赖原理与实例详解

    SpringBoot Starter依赖原理与实例详解

    SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰
    2022-09-09
  • Java杂谈之如何优化写出漂亮高效的代码

    Java杂谈之如何优化写出漂亮高效的代码

    不一致的代码会造成认知上的负担,在一个系统中,做类似的事情,却有不同的做法,或者起到类似作用的事物,却有不同的名字,让人困惑
    2021-09-09
  • Java设计模式之中介模式(Mediator模式)介绍

    Java设计模式之中介模式(Mediator模式)介绍

    这篇文章主要介绍了Java设计模式之中介模式(Mediator模式)介绍,本文讲解了为何使用Mediator模式、如何使用中介模式等内容,需要的朋友可以参考下
    2015-03-03

最新评论