Posts for the month of 十二月 2012

DocFetcher 1.1.5 试用及 zip 文件中文问题解决

自从接触 DocFetcher 以来, 就一直使用它来搜索自己的各类文档, 当时也总结过这个软件存在的问题, 详见 桌面搜索工具 DocFetcher 试用笔记;

概况

最近发现 DocFetcher 已经发布了 1.1.5 版本, 根据网站上的介绍, 1.1 版本经过完全重写(rewritten from scratch), 增加了大量的新特征(详见 http://docfetcher.sourceforge.net/wiki/doku.php?id=changes_in_v1.1), 包括我在 桌面搜索工具 DocFetcher 试用笔记 中所关注的:

  • Archive indexing: DocFetcher can now traverse archives. The following archive formats are supported: zip and zip-derived formats, 7z, rar, SFX zip, SFX 7z - 实际实验确认可以支持搜索压缩包中的内容, 而且支持嵌套压缩, 具体可以查看下面的截图;
  • Indexing of and searching in filenames - 可以按照文件名查找;

经过简单试用, 觉得这个版本还是值得升级的, 随后发现在搜索 zip 格式压缩包里面的内容时, 中文文件名会变成乱码. 具体现象如下图所示, 虽然可以索引压缩文件中的内容, 但是 zip 格式压缩包中中文文件名显示为乱码, 而 7z 和 rar 格式则显示正确:

下载代码(git clone http://git.code.sf.net/p/docfetcher/code docfetcher-code)研究了一下, 发现 DocFetcher 使用了 truezip 来进行 zip 格式压缩文件的搜索(支持 jar|tar|tar.bz2|tar.gz|tb2|tbz|tgz|zip 等多种格式), 而在 truezip 中, zip 格式默认使用的字符集为 IBM437:

... ...
public class ZipDriver
extends FsCharsetArchiveDriver<ZipDriverEntry>
implements ZipOutputStreamParameters, ZipFileParameters<ZipDriverEntry> {

    private static final Logger logger = Logger.getLogger(
            ZipDriver.class.getName(),
            ZipDriver.class.getName());

    /**
     * The character set for entry names and comments in &quot;traditional&quot;
     * ZIP files, which is {@code "IBM437"}.
     */
    private static final Charset ZIP_CHARSET = Charset.forName("IBM437");

    private final IOPool<?> ioPool;

    /**
     * Constructs a new ZIP driver.
     * This constructor uses {@link #ZIP_CHARSET} for encoding entry names
     * and comments.
     *
     * @param ioPoolProvider the provider for I/O entry pools for allocating
     *        temporary I/O entries (buffers).
     */
    public ZipDriver(IOPoolProvider ioPoolProvider) {
        this(ioPoolProvider, ZIP_CHARSET);
    }
    ... ...

而日常我们使用的 zip 压缩文件都是使用本地字符集进行压缩的(在中文环境下, 一般就是GBK), 继续研究发现, DocFetcher 使用 truezipTFile, 实现与 java.io.File 相似的方式统一访问文件系统目录和压缩文件(也就是把压缩文件看作一个目录), 而 TFile 内部则通过一个 TArchiveDetector 类型的成员变量来依据后缀名确定使用那种 "Driver" 操作具体的压缩文件;

默认情况下, 通过 TConfig.getArchiveDetector() 得到的 ArchiveDetector 是 TArchiveDetector.ALL, 此时在 TArchiveDetector 中实际使用 FsDriverLocator.SINGLETON 来获得所有加载的 "Driver", FsDriverLocator 会通过 ServiceLocator 查找并加载所有可用的 Driver, zip 格式相关 Driver 的定义实现在 ZipDriverService 中:

@Immutable
public final class ZipDriverService extends FsDriverService {

    private static final Map<FsScheme, FsDriver>
            DRIVERS = newMap(new Object[][] {
                { "zip", new ZipDriver(IOPoolLocator.SINGLETON) },
                { "ear|jar|war", new JarDriver(IOPoolLocator.SINGLETON) },
                { "odt|ott|odg|otg|odp|otp|ods|ots|odc|otc|odi|oti|odf|otf|odm|oth|odb", new OdfDriver(IOPoolLocator.SINGLETON) },
                { "exe", new ReadOnlySfxDriver(IOPoolLocator.SINGLETON) },
            });

    @Override
    public Map<FsScheme, FsDriver> get() {
        return DRIVERS;
    }
}

从上面这段代码可见, 系统默认得到的 ZipDriver 使用的是默认字符集 IBM437, 所以, 会产生中文问题;

另外, 从源代码还可以看到, JarDriver 默认使用的字符集是 UTF-8;

解决这个问题的方式是对 ZipDriverService 进行一定的调整, 以便通过环境变量或者 Java 系统属性来调整 ZipDriver 的默认字符集, 然后把这个 class 以 jar 补丁的形式, 放到 CLASSPATH 的最前面. 修改后的 ZipDriverService 代码如下:

@Immutable
public final class ZipDriverService extends FsDriverService {
        private static final String SYS_PROP_ZIP_CHARSET = ZipDriverService.class.getPackage().getName() + ".ZIP_CHARSET";
        private static final String ENV_VAR_ZIP_CHARSET = "TRUEZIP_ZIP_CHARSET";

        private static final ZipDriver buildZipDriver(){
                String charset = System.getProperty(SYS_PROP_ZIP_CHARSET);
                if (null!=charset && charset.trim().length() > 0){
                        return new ZipDriver(
                                        IOPoolLocator.SINGLETON, Charset.forName(charset.trim()));
                }
                charset = System.getenv(ENV_VAR_ZIP_CHARSET);
                if (null!=charset && charset.trim().length() > 0){
                        return new ZipDriver(
                                        IOPoolLocator.SINGLETON, Charset.forName(charset.trim()));
                }
                
                return new ZipDriver(IOPoolLocator.SINGLETON);
        }

    private static final Map<FsScheme, FsDriver>
            DRIVERS = newMap(new Object[][] {
                { "zip", buildZipDriver() },
                { "ear|jar|war", new JarDriver(IOPoolLocator.SINGLETON) },
                { "odt|ott|odg|otg|odp|otp|ods|ots|odc|otc|odi|oti|odf|otf|odm|oth|odb", new OdfDriver(IOPoolLocator.SINGLETON) },
                { "exe", new ReadOnlySfxDriver(IOPoolLocator.SINGLETON) },
            });

    @Override
    public Map<FsScheme, FsDriver> get() {
        return DRIVERS;
    }
}

编译后的 jar 补丁可以到附件中下载, 此 jar 文件可以放到 DocFetcher-1.1.5 的 patches 目录下, 然后按照下图的样子修改 DocFetcher.sh:

修改后即可正常处理 zip 格式压缩文件中的中文文件名了:

总结

补充说明

本文所提供的补丁没有在 Windows 系统上进行测试, 如果要在 Windows 系统中使用, 建议设置系统环境变量 set TRUEZIP_ZIP_CHARSET=GBK 后运行, 效果应该与 Linux 下一致;

顺便说一下, DocFetcher 对 rar 文件的解析是通过 java-unrar 实现的, 与 zip 压缩文件不同, rar 和 7z 压缩文件是通过所谓 SolidArchiveFactory 来处理的, SolidArchive 模式需要将文件解压到临时目录后再进行索引处理;

END

快速上传附件 - TracDragDropPlugin 插件

TracDragDropPluginhttp://trac-hacks.org/ 上面的一个 Trac 插件, 其主要功能就是使用 HTML5 drag-and-drop 方式, 快速上次附件.

前面一篇 Blog(这里) 具有 171 个截图, 这些图片附件就是使用 TracDragDropPlugin 批量上传的:
.

CentOS 6.0 虚拟机安装日志(截屏)(补 20111203)

在虚拟机中安装 CentOS 6.0

从 DVD1 iso 文件启动


安装开始界面


开始安装





















磁盘分区










选择"最小桌面"安装方式










安装完成, 重启







安装后的设置步骤

基本设置项目






Kdump 无法启用



进入系统




设置网络








虚拟机安装结束


重启, 检查更新













































安装 gcc 和内核头文件等










安装 vmware-tools

尝试


系统安装时已自带 vmware-tools


安装 telnet 命令






验证 sshd 已安装


安装 svn (客户端)








安装 7-zip 支持

































防火墙(iptables)设置








END

批处理中很有用的命令 WMIC(补 20120503)

原文来自 https://code.google.com/p/thinkbasenet/wiki/20120503_WMIC

最典型的用法

通过命令行中的一些内容查找程序

wmic process where "( (CommandLine LIKE '%_notepad_%') AND NOT(CommandLine LIKE '%_wmic_%' ) )"
  • 为了防止有 '%notepad%' 这样的环境变量, 所以使用了 '%_notepad_%' 这样的查询语法, 一般情况下, 直接使用 '%notepad%' 也是可以的.
  • 另外, 查询条件中 LIKE 操作符是不区分字符串的大小写的.

将 wmic 的输出由 unicode 转为 ascii

wmic 输出到 stdout 和 stderr 的内容都是 unicode 的,因此重定向到文件后,看起来会是这个样子:

使用如下的代码可以将 wmic 的输出由 unicode 转为 ascii:

:: 需要将 wmic 的输出由 unicode 转为 ascii
set TMP_WMIC_OUT=%TEMP%\wmic-process-list.txt
wmic /output:"%TMP_WMIC_OUT%" process where name="cmd.exe" get sessionid,commandline
cmd /A /C type "%TMP_WMIC_OUT%"

通过命令行中的一些内容结束程序

wmic process where "( (CommandLine LIKE '%_notepad_%') AND NOT(CommandLine LIKE '%_wmic_%' ) )" delete

参考

  • 关于 wmic 命令输出的 unicode 转 ascii
  • MSDN:
  • Microsoft TechNet
  • 来自 http://lgj573.iteye.com/blog/327432
    # wmic 获取硬盘固定分区盘符:
    wmic logicaldisk where "drivetype=3" get name
    
    # wmic 获取硬盘各分区文件系统以及可用空间:
    wmic logicaldisk where "drivetype=3" get name,filesystem,freespace
    
    # wmic 获取进程名称以及可执行路径:
    wmic process get name,executablepath
    
    # wmic 删除指定进程(根据进程名称):
    wmic process where name="qq.exe" call terminate
    # 或者用
    wmic process where name="qq.exe" delete
    
    # wmic 删除指定进程(根据进程PID):
    wmic process where pid="123" delete
    
    # wmic 创建新进程
    wmic process call create "C:\Program Files\Tencent\QQ\QQ.exe"
    
    # 在远程机器上创建新进程:
    wmic /node:192.168.1.10 /user:administrator /password:123456 process call create cmd.exe
    
    # 关闭本地计算机
    wmic process call create shutdown.exe
    
    # 重启远程计算机
    wmic /node:192.168.1.10/user:administrator /password:123456 process call create "shutdown.exe -r -f -m"
    
    # 更改计算机名称
    wmic computersystem where "caption='%ComputerName%'" call rename newcomputername
    
    # 更改帐户名
    wmic USERACCOUNT where "name='%UserName%'" call rename newUserName
    
    # wmic 结束可疑进程(根据进程的启动路径)
    wmic process where "name='explorer.exe' and executablepath<>'%SystemDrive%\\windows\\explorer.exe'" delete
    
    # wmic 获取物理内存
    wmic memlogical get TotalPhysicalMemory|find /i /v "t"
    
    # wmic 获取文件的创建、访问、修改时间
    @echo off
    wmic datafile where name^="c:\\windows\\system32\\notepad.exe" get CreationDate^,LastAccessed^,LastModified
    
    # wmic 全盘搜索某文件并获取该文件所在目录
    wmic datafile where "FileName='qq' and extension='exe'" get drive,path
    
    for /f "skip=1 tokens=1*" %i in ('wmic datafile where "FileName='qq' and extension='exe'" get drive^,path') do (set "qPath=%i%j"&@echo %qPath:~0,-3%)
    
    # 获取屏幕分辨率
    wmic DESKTOPMONITOR where Status='ok' get ScreenHeight,ScreenWidth
    
    # 获取U盘盘符,并运行U盘上的QQ.exe
    @for /f "skip=1 tokens=*" %i in ('wmic logicaldisk where "drivetype=2" get name') do (if not "%i"=="" start d:\qq.exe)
    
    # 获得进程当前占用的内存和最大占用内存的大小:
    wmic process where caption='filename.exe' get WorkingSetSize,PeakWorkingSetSize
    # 把内存大小改成KB(MB的话可能有小数)
    @echo off
    for /f "skip=1 tokens=1-2 delims= " %%a in ('wmic process where caption^="conime.exe" get WorkingSetSize^,PeakWorkingSetSize') do (
    set /a m=%%a/1024
    set /a mm=%%b/1024
    echo 进程conime.exe现在占用内存:%m%K;最高占用内存:%mm%K
    )
    pause 
    

Ubuntu 10.04 上通过无线共享互联网连接(补 20120222)

原文来自 https://code.google.com/p/thinkbasenet/wiki/20120222_Ubuntu_Wifi_Ad_hoc

参考页面

http://hi.baidu.com/myl71/blog/item/75bb0944bb44362acefca318.html ;

其主要内容如下:

首先准备好带无线网卡的笔记本电脑一台;

Ubuntu10.04操作系统一套;

能正常连接网络的网线一根;

进入ubuntu 10.04后在右上角工具栏的网络连接上点右键,点“新建连接” ,
然后输入你想新建的无线路由器的名字,之后设定加密方式,如果是想满足宿舍
内的网络共享你只需要设置一个wep的加密方式,然后就可以新建成功了,之后
您就可以叫您的朋友搜索无线网络了,然后连接就可以了。

经我的观察,ubuntu下面新建的wifi效果非常的好,网络稳定,网速也非常的
快。适合喜欢无线冲浪的您。

新建的网络连接属性(截屏)

其他信息

  • 其他电脑连接时不需要设置IP, 采用DHCP自动获取IP地址即可;
  • 实际连接后 Ubuntu 机器的网络情况如下, 其中 10.42 网段应该是系统自动分配的, 通过 Wifi 连接到 Ubuntu 上的其他机器的地址应该都在这个网段.
    .

END

Linux 下定期屏幕截屏脚本(补 20111120)

原文来自 https://code.google.com/p/thinkbasenet/wiki/20111120_ScreenRecorderShellInLinux

概述

在上一篇 Windows 和 Linux 下定期屏幕截屏的方法 中提到了可以使用 ImageMagickimport 命令完成截屏过程, 本文基于 import 命令, 提供两个脚本, 分别用于定期截取当前活动窗口, 以及定期截取指定窗口;

脚本

主要技术说明

import 命令

  • -screen 参数: 不了解 X 的细节, 猜测对于一个典型的 X 窗口, 其中的工具提示、菜单等其实是有独立的 window id 的, 那么在指定 window id 截屏时, 可能是截取不到这些内容的, 使用 -screen 参数可以解决这个问题:
    • 没有 -screen 参数时的内容:
    • 加上 -screen 参数:

取得窗口的 window id 和 process id

  1. 获取当前活动窗口的 window id:
    • xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)"| cut -d ' ' -f 5
  2. 使用 xwininfo 选择一个窗口并获取其 window id:
    • xwininfo | grep "xwininfo: Window id:" | cut -d ' ' -f 4
  3. 获取窗口($WIN_ID)对应的进程 ID:
    • xprop -id $WIN_ID | grep "_NET_WM_PID(CARDINAL)" | cut -d ' ' -f 3

比较截屏文件是否一致

  • 使用 cmp 命令即可.

END

Windows 和 Linux 下定期屏幕截屏的方法(补 20101114)

原文来自 https://code.google.com/p/thinkbasenet/wiki/20101114_ScreenShotAsFilesInWindowsAndLinux

截屏并存储到文件的方法, 主要是可以用于录制操作视频, 或者日志重要系统操作过程, 以及测试过程等.

简介

一直以来使用 Wink 作为屏幕录制的首选软件, 但是 Wink 存在一个很麻烦的问题, 就是在录制途中, 所有的屏幕截屏都存储在内存里, 因此在很长时间的操作中, 往往会造成内存溢出, 导致前功尽弃.

有一个想法是写一个录制屏幕并且及时存储到图片文件的软件, 最初的想法是使用 Java 来写, 但是一直都没有开始; 今天无意中看到了 nircmd 这个软件, 其中的命令 savescreenshot 可以较好的完成这个要求:

nircmdc.exe loop 1000 2000 savescreenshot c:\temp\scr~$currdate.MM_dd_yyyy$-~$currtime.HH_mm_ss$.png 

loop 1000 2000 代表循环 1000 次, 间隔时间 2 秒(2000 毫秒);

使用 nircmdc 可以保证 1000 次循环完成之前, 命令行一直停留在这个命令上, 方便不需要的时候使用 Ctrl-C 结束截屏过程;

另外还可以使用 savescreenshotwin 命令保存当前活动窗口的命令;

Linux 下的处理方法

使用 nircmdc 可以在 Windows 下实现定时截屏的要求, 但是在 Linux 下又如何实现呢? 经过一番搜索, 大致的解决方案如下:

  1. 基于 ImageMagick, 使用其 import 命令完成截屏过程, 基本语法为:
    import -window <Window ID> <FileName>.png
    
  2. 如果需要截取整个屏幕, 可以使用 root 作为 Window ID, 例如:
    import -window root MyScreenshot3.png
    
  3. 如何实现截取当前活动窗口呢? 可以使用如下命令得到当前活动窗口 ID:
    xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)"| cut -d ' ' -f 5
    
  4. 20111120 添加 - Linux 下定期屏幕截屏脚本;

下载

其它

  1. 减少文件大小
    • 如果屏幕内容一直不变, 那么就会出现重复录取同一个画面的情况, 应该可以通过一个脚本使用 md5sum 等命令检查两张图片是否完全一样, 删除重复内容的图片, 这样就可以实现减少文件大小的目的了.

参考资料

  1. http://tips.webdesign10.com/how-to-take-a-screenshot-on-ubuntu-linux
    • "How to Take a Screenshot in Linux (Ubuntu)", 描述了在 Ubuntu 上几种截屏的方法;
  2. http://www.charry.org/docs/linux/ImageMagick/ImageMagick.html
    • "我的ImageMagick使用心得", ImageMagick 的中文介绍;
  3. http://www.ruby-forum.com/topic/165740#728314
    • "Title from current active window", Ruby-Gnome 2 论坛的讨论;

END

桌面搜索工具 DocFetcher 试用笔记(补 20110416)

最初发布在 https://code.google.com/p/thinkbasenet/wiki/20110416_DocFetcherTrialRun ;

简介

在 Ubuntu 上一直使用 Beagle Search( http://beagle-project.org/ )来对一些有用的文档进行全文检索, 今天想起这件事, 上网找了一圈, 发现 DocFetcher( http://sourceforge.net/projects/docfetcher/ ) 也是不错的一个桌面搜索工具.

在 sf.net 网站可以下载到的 DocFetcher 最新版本是 1.0.3 (2010-03-18 更新), 提供了 Win32 安装程序、Linux deb 包, 以及一个可用于 Windows 及 Linux 环境的 "portable" 版本, 解压后即可使用, 运行时产生的配置及索引数据都存放在程序目录下, 方便存放到 U 盘等移动设备上使用 :)

主要特色

  • 基于 Java SWT 开发, 跨平台;
  • 支持 txt、html、MS Office、Open Office、PDF等常用的文件格式, 基本上够用了;
  • 界面比较简单, 但是使用很方便, 基本上只要两步:
    1. 添加要索引的目录, 建立索引;
    2. 输出要查询的字符串, 进行查找;
  • 中文支持不错;

需要解决的问题

  • 最主要的缺点(我认为)是不能检索压缩包, 这样对那些压缩打包后的文档就比较难搜索了;
  • 不支持对文件名进行查找;
  • 对 UTF-8 格式的文本文件, 似乎只能认识英文;

中文化

  • 这个版本的 lang 目录下有 fr、de 等几种语言的资源文件(.properties), 但是没有中文语言的资源文件, 不过很容易通过对 Resource.properties文件翻译产生中文语言包.
  • 今天大致翻译了一下, 如果需要有这个中文语言包的话, 可以在这里下载;

后记

  • 20110416
    • Puggle( http://puggle.sourceforge.net/index.html )也是一个简单易用的 Java 桌面搜索工具, 而且支持 zip 和 rar 格式文档的搜索, 以及针对文件名字的查找(不过, 似乎不支持扩展名 :$).
  • 20121203
    • 发现目前 DocFetcher 已经升级到 1.1.5 版本了, 已经支持对 zip、7z、rar 等格式的压缩文件进行索引, 具体情况有待试验:

      Between version 1.0.3 and version 1.1 beta 1, DocFetcher was rewritten from scratch, resulting in a large number of new features and changes. This page gives an overview of the most important ones.

END

thinkbase.net 站点 logo / favorites icon 调整

默认情况下 PortableTrac 的 logo 为 http://trac-hacks.org/chrome/site/trachacks_banner.png, favorites icon 则为 Trac 默认图标 /chrome/common/trac.ico.

现在 thinkbase.net 的 logo 和 favorites icon 是在 OpenOffice 相关图标的基础上修改得到的, 来源为下面两个图标:

  • logo 的来源:
    • 本网站 logo 的来源文件
  • favorites icon 的来源:
    • 本网站 favorites icon 的来源文件

logo 上的文字是使用 GIMP 修改上去的, 使用的是 文泉驿等宽正黑 字体, GIMP 源文件 (.xcf 格式) 见附件 thinkbase-logo.xcf;

关于这两个图标的详细来源和 License, 请详细参考 ICON FINDER 上的相关页面:

站点 logo / favorites icon 调整的方法参考 ZhTracInterfaceCustomization ;