- JAR 文件
- Java Resource
- 应用程序的配置
JAR 可以将 Java 应用程序打包,JAR 文件可以包含类文件,也可以包含资源文件. JAR 文件采用 Zip 压缩格式.
JAR 命令:
? Desktop jar cvf sample.jar corejava | iconv -f gbk -t utf-8标明清单(manifest)增加:corejava/(读入= 0) (写出= 0)(存储了 0%)增加:corejava/.DS_Store(读入= 6148) (写出= 425)(压缩了 93%)增加:corejava/inheritance/(读入= 0) (写出= 0)(存储了 0%)增加:corejava/inheritance/ArrayStoreExceptionTest.class(读入= 787) (写出= 455)(压缩了 42%)增加:corejava/inheritance/Base.class(读入= 651) (写出= 391)(压缩了 39%)增加:corejava/inheritance/DynamicBinding.class(读入= 654) (写出= 386)(压缩了 40%)增加:corejava/inheritance/Sub.class(读入= 546) (写出= 354)(压缩了 35%)增加:corejava/inner/(读入= 0) (写出= 0)(存储了 0%)增加:corejava/inner/InnerClassTest.class(读入= 744) (写出= 469)(压缩了 36%)增加:corejava/inner/TalkingClock$TimePRinter.class(读入= 1315) (写出= 689)(压缩了 47%)增加:corejava/inner/TalkingClock.class(读入= 933) (写出= 527)(压缩了 43%)增加:corejava/interfaces/(读入= 0) (写出= 0)(存储了 0%)增加:corejava/interfaces/CloneTest.class(读入= 1372) (写出= 757)(压缩了 44%)增加:corejava/interfaces/Employee.class(读入= 1867) (写出= 994)(压缩了 46%)增加:corejava/interfaces/Employee2.class(读入= 308) (写出= 227)(压缩了 26%)增加:corejava/interfaces/ProxyTest.class(读入= 1427) (写出= 819)(压缩了 42%)增加:corejava/interfaces/SortTest.class(读入= 599) (写出= 354)(压缩了 40%)增加:corejava/interfaces/TimePrinter.class(读入= 1061) (写出= 580)(压缩了 45%)增加:corejava/interfaces/TimerTest.class(读入= 854) (写出= 512)(压缩了 40%)增加:corejava/interfaces/TraceHandler.class(读入= 1379) (写出= 762)(压缩了 44%)增加:corejava/reflection/(读入= 0) (写出= 0)(存储了 0%)增加:corejava/reflection/ArrayGrowTest.class(读入= 1897) (写出= 1054)(压缩了 44%)增加:corejava/reflection/MethodPointerTest.class(读入= 1869) (写出= 992)(压缩了 46%)增加:corejava/reflection/ObjectAnalyzer.class(读入= 3411) (写出= 1807)(压缩了 47%)增加:corejava/reflection/ReflectionTest.class(读入= 4412) (写出= 2198)(压缩了 50%)
manifest在生成 JAR 文件时,每个 JAR 文件还包含一个用于描述归档特征的清单文件(manifest),名为 MANIFEST.MF,位于 META-INF 子目录中(META-INF/MANIFEST.MF)。
manifest 结构
Manifest-Version: 1.0描述这个归档文件的行Name: Woozle.class描述这个文件的行Name: com/mycompany/mypkg/描述这个包的行
可运行 JAR 文件jar cvfe MyProgram.jar corejava.reflection.MethodPointerTest corejava
可以指定程序的入口. 在 manifest 会生成:
Manifest-Version: 1.0Created-By: 1.6.0_65 (Apple Inc.)Main-Class: corejava.inheitance.ArrayStoreExceptionTest
java -jar MyProgram.jar
即可运行.
应用程序的资源可以是:
- 图像和声音文件.
- 带有消息字符串和按钮标签的文本文件.
- 二进制数据文件.
Java 的资源不同 Windows, Windows 的资源属于 exe 文件的一部分,通过标准的程序设计访问;而 Java 资源作为单独的文件存储,不是类文件的一部分存储,对资源的访问和解释由每个类自己胜任.
对资源的访问和解释由每个类自己胜任.e.g.
package corejava.resource;import javax.swing.*;import java.awt.*;import java.io.InputStream;import java.net.URL;import java.util.Scanner;/** * Created by guolong.fan on 15/4/27. */public class ResourceTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { ResourceTestFrame frame = new ResourceTestFrame(); frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); }}class ResourceTestFrame extends JFrame { public ResourceTestFrame() { setTitle("ResourceTest"); setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); URL aboutURL = getClass().getResource("about.gif"); Image img = Toolkit.getDefaultToolkit().getImage(aboutURL); setIconImage(img); JTextArea textArea = new JTextArea(); InputStream stream = getClass().getResourceAsStream("about.txt"); Scanner in = new Scanner(stream); while (in.hasNext()) { textArea.append(in.nextLine() + "/n"); } add(textArea); } public static final int DEFAULT_WIDTH = 300; public static final int DEFAULT_HEIGHT = 300;}
对应用程序进行配置,并且将配置保存起来,当再次运行应用程序时读取配置。Java 提供了两种方式:Properties 和 Preference。
put & store & load & get
PropertiesProperty Map: 键/值对,通常用于存放配置信息.
package corejava.resource;import javax.swing.*;import java.awt.*;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;/** * Created by guolong.fan on 15/4/27. */public class PropertiesTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { PropertiesFrame frame = new PropertiesFrame(); frame.setVisible(true); } }); }}class PropertiesFrame extends JFrame { public PropertiesFrame() { // Properties String userDir = System.getProperty("user.home"); File propertiesDir = new File(userDir, ".corejava"); if (!propertiesDir.exists()) propertiesDir.mkdir(); properitesFile = new File(propertiesDir, "program.properties"); // 设置默认设置 Properties defaultSettings = new Properties(); defaultSettings.put("left", "0"); defaultSettings.put("top", "0"); defaultSettings.put("width", "" + DEFAULT_WIDTH); defaultSettings.put("height", "" + DEFAULT_HEIGHT); defaultSettings.put("title", ""); setting = new Properties(defaultSettings); if (properitesFile.exists()) try { // 如果文件存在,则从文件导入 FileInputStream in = new FileInputStream(properitesFile); setting.load(in); } catch (IOException ex) { ex.printStackTrace(); } int left = Integer.parseInt(setting.getProperty("left")); int top = Integer.parseInt(setting.getProperty("top")); int width = Integer.parseInt(setting.getProperty("width")); int height = Integer.parseInt(setting.getProperty("height")); setBounds(left, top, width, height); String title = setting.getProperty("title"); if (title.equals("")) title = JOptionPane.showInputDialog("Please supply a frame title"); if (title == null) title = ""; setTitle(title); // 关闭 window 时 将当前设置写入配置文件中 addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent windowEvent) { setting.put("left", "" + getX()); setting.put("top", "" + getY()); setting.put("width", "" + getWidth()); setting.put("height", "" + getHeight()); setting.put("title", getTitle()); try { FileOutputStream out = new FileOutputStream(properitesFile); setting.store(out, "Program Properties"); } catch (IOException e) { e.printStackTrace(); } super.windowClosing(windowEvent); } }); } private File properitesFile; private Properties setting; public static final int DEFAULT_WIDTH = 300; public static final int DEFAULT_HEIGHT = 300;}
生成的配置文件:
#Program Properties#Sun May 03 17:11:24 CST 2015height=336width=420left=360top=23title=PropertiesTest
put & store & load & get
Properties 类简化读取和保存配置. 但是配置文件存放无法放在主目录中(有些操作系统没有主目录的概念); 没有标准的配置文件命名的规则,导致配置文件名冲突.
Java SE 1.4 提供了 Preferences 类提供一个与平台无关的中心知识库.中心知识库实现是透明,通常 Windows 采用注册表,而 linux 采用放在本地文件系统中.
Preferences 的中心知识库采用树状结构,每个节点的路径类似于包名,这样可以避免命名冲突。每个节点都有一个用来存放 key/value 的独立表。
为了增加灵活性,系统中有多棵并行的树。系统树用来存放全体用户的公共信息,每个程序的使用者拥有一棵树。Preferences 类操作的是'当前用户'的用户树。
访问用户树: Preferences root = Preferences.userRoot();
访问系统树: Preferences root = Preferences.systemRoot();
访问具体节点(通过路径名): Preferences node = root.node("/com/mycompany/myapp");
访问具体节点(通过包名): Preferences node = Preferences.userNodeForPackage(obj.getClass());
or Preferences node = Preferences.systemNodeForPackage(obj.getClass());
通过节点来 get/put.
String get(String key, String defVal);int getInt(String key, int defVal);... ...put(String key, String value);putInt(String key, int value);... ...
采用 xml 格式导入/导出.
void exportSubtree(OutputStream out);void exportNode(OutputStream out);void importPreferences(InputStream in);
新闻热点
疑难解答