如何使Windows文件关联与非ASCII文件名一起使用?

时间:2012-11-21 13:07:30

标签: java windows unicode batch-file file-association

我需要为某种文件类型注册文件关联 - 事实上,我只需要使用某些参数和该文件的名称启动某个Java程序。

我得到了以下内容:

// in fff-assoc.cmd file:
assoc .fff=SomeFile
ftype SomeFile=java -jar some.jar <arguments1> "%%1" <arguments2>

适用于ASCII文件名。但是当我尝试双击某个名称中带有非ASCII符号的文件时,传递的参数看起来像“????” (每个char的int值= 63)。

如何修复这些关联?

3 个答案:

答案 0 :(得分:2)

如果bobince所说的是准确的并且你无法可靠地直接将数据传递给java,那么另一种解决方案就是用另一种语言(例如C,C ++或C#)编写一个小的“垫片”程序。

这个想法是程序将输入作为UNICODE进行编码,对其进行编码以便只使用ASCII字符表示(例如使用base64,或者甚至像编码每个字符那样简单的数字等价物),然后组装命令line参数使用和使用CreateProcess启动java本身。

您的Java代码可以“撤消”编码,重建UNICODE名称并继续使用它。这是一种迂回的方式,需要一个额外的软件组件,但它应该解决上面详述的限制,如果确实这是一个实际的限制。

更新:这是填充程序的基本代码。它将输入编码为整数序列,以冒号分隔。它在错误检查方面做的并不多,你可能想稍微改进它,但它至少应该让你开始并朝着正确的方向前进。

您应该使用Visual Studio Express(如果您还没有Visual Studio)并创建一个新的Visual C ++项目,选择“Win32”并选择“Win32 Project”。选择“Win32应用程序”。创建项目后,替换使用以下代码显示的.cpp文件中的所有内容:

#include "stdafx.h"
#include <string>

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR lpCmdLine, int)
{
    std::string filename;

    while((lpCmdLine != NULL) && (*lpCmdLine != 0))
    {
        if(filename.length() != 0)
            filename.append(":");

        char buf[32];

        sprintf(buf, "%u", (unsigned int)(*lpCmdLine++));

        filename.append(buf);   
    }

    if(filename.length() == 0)
        return 0;

    PROCESS_INFORMATION pi;
    memset(&pi, 0, sizeof(PROCESS_INFORMATION));

    STARTUPINFOA si;
    memset(&si, 0, sizeof(STARTUPINFOA));
    si.cb = sizeof(STARTUPINFOA);

    char *buf = new char[filename.length() + 256]; // ensure that 256 is enough for your extra arguments!

    sprintf(buf, "java.exe -jar some.jar <arguments1> \"%s\" <arguments2>", filename.c_str());

    // CHECKME: You hard-coded the path for java.exe here. While that may work on your system
    // is it guaranteed that it will work on every system?

    if(CreateProcessA("C:\\Program Files\\Java\\jre7\\bin\\java.exe", buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
    {
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }

    delete[] buf;

    return 0;
}

你应该能够很容易地计算出如何编译的细节等等。

答案 1 :(得分:1)

  

我只需要使用某些参数和该文件的名称启动某个Java程序。

不幸的是,由于Java用于接收参数输入的标准C库的MS实现(以及其他内容),这种'just'实际上是不可能的。除非您直接使用本机Win32 API,否则绕过标准Java或C接口,

请参阅this question了解背景信息。

答案 2 :(得分:1)

从命令行调用java时,您可以指定参数的编码(将用于在args[]中创建字符串):

java -jar -Dsun.jnu.encoding=cp1252 yourFileName

使用非ASCII字符时,指定的字符集会对args[0]的值产生影响。不确定这是否适用于文件关联。

注意:我不确定该参数的其他用途 - this post似乎没有。