分类 其他 下的文章

在工作环境中,免不了需要配置好多环境,自己配置的,别人配置的。所以,知道哪些IP的哪些端口开放,就可以做很多事情了。

// 新建主机地址
InetAddress  hostAddress = InetAddress.getByName("0.0.0.0");

// 根据主机名和端口号创建套接字地址
SocketAddress sockAddr = new InetSocketAddress(hostAddress, 80);

// 新建套接字
Socket socket = new Socket();

// 将此套接字连接到目标主机
socket.connect(sockAddr, 1000);
// connect操作未抛异常,说明该端口可用
// Do sth...... 

// 关闭套接字
socket.close();

周四刚从济南回来,周五一到公司,就安排了一个为平台软键盘集成手写输入法的任务。说实话,我对这种研究探索实践的任务还是很感兴趣的。

概述

Tegaki

Tegaki (http://tegaki.org/),是一款开源的中文和日文的手写识别项目。它有如下特点:

  • 免费并且开源
  • 跨平台
  • 关注于中文(简体中文和繁体中文)和日文
  • 支持两种识别引擎(Zinnia和Wagomu)
  • 渴望在台式PC和移动设备上均可工作

安装请按照文档(http://tegaki.org/userdoc/)进行。除了下载主程序外,还需要对应识别引擎的model文件,放在相应的路径下。

Zinnia

Zinnia (http://zinnia.sourceforge.net/),是一个简单的,可定制化的和跨平台的在线手写识别系统,它建立在SVM(Support Vector Machines,支持向量机)的基础上。Zinnia接受用户笔迹输入,这些笔迹表现为一系列坐标的序列,然后,通过SVM输入前n个最佳识别。为了跨平台, Zinnia并不包含任何的渲染功能,即获得用户输入的功能并不包含在内。除了识别功能,Zinnia还提供了一个训练模型,可以花费很小的代价就可以创造一个手写识别系统。它有如下特点:

  • 使用SVM,识别准确率高
  • 跨平台和紧凑--可以运行在POSIX和Windows上(建立在C++/STL的基础上)
  • 提供了线程安全的C/C++/Perl/Ruby/Python库
  • 识别速度快(每秒50到100个字符)
  • 快速训练

- 阅读剩余部分 -

在工作中,会遇到要在CMD中执行命令和命令行的情况。比如要调出Windows的计算器……(确实有这样的需求)。

那么怎样调用才能易操作,易扩展并没有副作用呢?
推荐使用ProcessBuilder。示例代码如下:

try {
    ProcessBuilder processBuilder = 
        new ProcessBuilder("calc.exe");            
    processBuilder.start();
} catch (IOException e) {
    // TODO: handle exception
    e.printStackTrace();
}

首先实例化一个ProcessBuilder,参数就是要执行的命令,然后调用ProcessBuilder.start()方法即可。

注意,这里要执行的命令是要加入到系统Path下的,否则无法调用。
如果你的命令没有加入到系统Path下,那么可以给ProcessBuilder指定工作目录,将其目录指定为包含你要执行命令的目录即可:

processBuilder.directory(new File("E://mydir/"));

如果你要执行的命令只有通过系统CMD才能执行,比如echo,那么怎么办呢?

ProcessBuilder processBuilder = new ProcessBuilder
    ("cmd.exe","/c","echo","Hello, world!");

第一个参数是要执行的命令,后面的参数都是该命令的参数。通过在命令行执行命令即cmd.exe /c即可。但是需要注意的事,第一个参数必须为执行的命令,后面每个参数都是该命令的参数。

比如

ProcessBuilder processBuilder = new ProcessBuilder
    ("cmd.exe","/c","ping www.chengjf.com");

或者

ProcessBuilder processBuilder = new ProcessBuilder
    ("ping", "www.chengjf.com");

都是正确的。但是如果

ProcessBuilder processBuilder = new ProcessBuilder
("ping www.chengjf.com");

那么就是错误的,会抛出IOException。

如果你要获得执行的结果,咋整?比如,你执行了一个ping命令,想拿到执行结果。

try {
    ProcessBuilder processBuilder = 
        new ProcessBuilder("ping","www.chengjf.com");            
    Process process = processBuilder.start();
    InputStream inputstream = process.getInputStream();
    // Windows中文操作系统此处要使用gbk转码,否则输出会乱码
    BufferedReader bufferedReader = 
        new BufferedReader(new InputStreamReader(inputstream,"gbk"));

    String rs = null;
    while((rs = bufferedReader.readLine()) != null){
        System.out.println(rs);
    }
} catch (IOException e) {
    // TODO: handle exception
    e.printStackTrace();
}

通过ProcessBuilder.start()会生成一个Process,通过调用Process.getInputStream()方法可以获得结果的输入流。这里推荐使用BufferedReader,可以实时获取到命令行的输出,而不是等到命令执行完毕再一起输出。

Preferences API与对象序列化相比,前者与对象持久性更密切,因为它可以自动存储和读取信息。不过,它只能用于小的、受限的数据集合——我们只能存储基本类型和字符串,并且每个字符串的存储长度不能超过8K(不是很小,但我们也并不想用它来创建任何重要的东西)。顾名思义,Preferences API用于存储和读取用户的偏好(preferences)以及程序配置项的设置。

Preferences是一个键-值集合(类似映射),存储在一个节点层次结构中。尽管节点层次结构可用来创建更为复杂的结构,但通常是创建以你的类名命名的单一节点,然后将信息存储于其中。

    // : io/PreferencesDemo.java
    import java.util.prefs.*;

    public class PreferencesDemo {
    public static void main(String[] args) throws Exception {
        Preferences prefs = Preferences.userNodeForPackage(PreferencesDemo.class);
        prefs.put("Location", "Xi'an");
        prefs.put("Name", "chengjf");
        prefs.putInt("Age", 24);
        prefs.putBoolean("Is he a coder?");
        int usageCount = prefs.getInt("UsageCount", 0);
        usageCoun++;
        prefs.putInt("UsageCount", usageCount);
        for(String key : prefs.getKeys()){
            System.out.println(key + " : " + prefs.get(key, null));
        }
        // You must always provide a default value:
        System.out.println("How old is he? " + prefs.getInt("Age", 0);
    }
    }

    // Output: (Sample)
    ......
    //

最好将“user”用于个别用户的偏好,将“system”用于通用的安装配置。
尽管我们不一定非要把当前的类作为节点标示符,但这仍不失为一种很有用的方法。

一旦我们创建了节点,就可以用它来加载或者读取数据了。在这个例子中,向节点载入了各种不同类型的数据项,然后获取其keys()。它们是以String[]的形式返回的,如果你习惯于keys()属于集合类库,那么这个返回结果可能并不是你所期望的。注意get()的第二个参数,如果某个关键字下没有任何条目,那么这个参数就是所产生的默认值。当在一个关键字集合内迭代时,我们总要确信条目是存在的,因此用null作为默认值是安全的,但是通常我们会获得一个具名的关键字,就像下面这条语句:

    prefs.getInt("Companions", 0);

在通常情况下,我们希望提供一个合理的默认值。实际上,典型的习惯用法可见于下面几行:

    int usageCount = prefs.getInt("UsageCount", 0);
    usageCount++;
    prefs.putInt("UsageCount", usageCount);

这样,在我们第一次运行程序时,UsageCount的值是0,但在随后引用中,它将会是非零值。

在我们运行PreferencesDemo.java时,会发现每次运行程序时,UsageCount的值都会增加1,但是数据存储到哪里了呢?在程序第一次运行之后,并没有出现任何本地文件。Preferences API利用合适的系统资源完成了这个任务,并且这些资源会随着操作系统不同而不同。例如在Windows里,就是用注册表(因为它已经有“键值对”这样的节点对层次结构了)。但是最重要的一点是,它已经神奇般地为我们存储了信息,所以我们不必担心不同的操作系统是怎么运作的。