电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

驯服Tiger之访问环境变量和调用子进程


发布日期:2023/7/16
 

访问平台专有的信息并不是一件容易的事虽然可以使用 Runtimeexec() 创建进程但由于平台之间的差异构造参数集常常令人头痛不已此外 System 的 getenv() 方法从开始进行 Java 编程就遭到反对

什么时候一个遭到反对的方法不再被反对呢?使用 System 的 getenv() 方法时就会遇到这种情况Tiger 以 年正式发布之前的 Java 平台为基础它没有抛弃该方法同时还提供了一个新的类 ProcessBuilder (属于包 javalang )用它来创建进程并与系统进程交互

访问环境变量

虽然我个人并不想退回到原来使用 AWT 组件的事件模型但是早期的 Java 平台版本(称为 alpha 版)有一个很好的特性即能够访问环境变量该方法和当时编写一次随处运行的颂词背道而驰因此当 Java 平台发布 版时 System 的 getenv() 方法受到了抨击虽然 版为何抛弃原来的一些内容一直令我迷惑不解但我常常看到该方法引起新入门开发人员的兴趣时间回到 您现在终于能够使用这个方法了如清单 所示该方法的使用很简单

清单 调用 getenv

public class EnvTest {

public static void main(String args[]) {

Systemoutprintln(Systemgetenv(args[]));

}

}

只要在命令行中随 getenv 调用传入变量的名称就可以得到它的当前值比如在我那台用了两年的桌面机上如果输入参数 PROCESSOR_IDENTIFIER 就会得到清单 所示的结果

清单 getenv 的输出结果

java EnvTest PROCESSOR_IDENTIFIER

x Family Model Stepping GenuineIntel

首先要注意的是方法名 getenv() 它完全采用小写形式而不是采用您所预料的大小写混合形式( getEnv() )这是因为在正式发布之前的最初命名方法就是这样的其次访问环境变量常常要使用平台专用的代码如果确实希望这样做也可以但这样就偏离了百分之百的纯 Java 模型上述代码本身仍然是纯粹的 Java 代码因此使用该方法并不完全违背这一原则但是使用了这么多年的系统属性之后使用 getenv() 感觉怪怪的

Tiger 提供了两个版本的 getenv() 方法而不是一个第二个版本返回与系统中当前设置的所有环境变量对应的名/值对(namevalue pairs)清单 说明了这种新方法的应用并打印出了所有环境变量的键和值

清单 访问所有的环境变量

import javautilMap;

public class EnvDump {

public static void main(String args[]) {

for (MapEntry entry: Systemgetenv()entrySet()) {

Systemoutprintln(entrygetKey() + / +

entrygetValue());

}

}

}

理解 ProcessBuilder

这为我们带来了一个新的类 javalangProcessBuilder 平台的早期版本允许通过 Runtime 类的 exec() 方法创建本机进程该方法仍然有效但是因为能以 String 数组作为参数以 File 参数作为工作目录所以用这种方法定制子进程比较困难使用 ProcessBuilder 可以简化这个过程它提供了 directory(File) 方法来改变进程的工作目录可以用 environment() 方法在进程空间中添加和删除环境变量清单 说明了 ProcessBuilder 的一种简单用法它使用 ipconfig 命令获得 Internet 配置信息该方法适用于多数平台否则可以将 ipconfig 改写成所用平台上的工作命令启动进程构造程序之后需要获得其 InputStream 以读入所创建进程的结果

清单 使用 ProcessBuilder

import javaio*;

public class ProcessTest {

public static void main(String args[]) throws IOException {

Process p = new ProcessBuilder(ipconfig)start();

InputStream is = pgetInputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(is));

String line;

while ((line = brreadLine()) != null) {

Systemoutprintln(line);

}

}

}

如清单 所示该程序的运行结果与在命令行中执行 ipconfig 所得到的结果类似(您得到的结果看起来可能有所不同)

清单 ProcessBuilder 的输出结果

Windows IP Configuration

Ethernet adapter Local Area Connection:

Connectionspecific DNS Suffix :

IP Address :

Subnet Mask :

Default Gateway :

如前所述 ProcessBuilder 类不仅能生成新的进程而且还能获得其结果在调用其 start() 方法之前还可以调整进程所执行的上下文如果不喜欢环境变量您可以使用 environment 获得当前设置并调用 clear() 清除映射如果需要添加环境变量可以调用 environment 获得当前设置然后通过 put(name value) 添加新的变量如果希望使用新的工作目录可以调用 directory() 并提供新的工作目录作为 File 对象就是这么简单使用表示将运行的命令及其参数的数目可变的字符串参数来创建 ProcessBuilder 一旦使用新的环境变量和工作目录配置 ProcessBuilder 就可以调用 start() 来执行命令

结束语

您希望您所喜欢的方法在遭到反对之后再受到欢迎吗?当然有时候一个受到抨击的方法虽然从没在 Java 发行版本中受到真正的支持但它可能重新获得新生只要有足够多的用户在 Sun 的 Bug Parade 上呼吁和投票开发人员就可以改变 Java 平台的演进方向虽然我曾怀疑过时的 AWT 事件模型会卷土重来——尽管每个人都这样要求但只是一些简单的问题(如访问环境变量)最终得到了 Java 平台的支持小心地使用它除了反对 getenv 的问题之外 ProcessBuilder 还提供了一种创建本机进程的简单方法应该用它来代替所有过时的 Runtimeexec() 调用开始重构吧!

上一篇:深入了解JVM内存结构

下一篇:浏览器访问一个地址的过程