关于用registry.jar操作windows注册表的问题,大家来看看啊

时间:2022-11-16 15:35:46
用registry.jar操作windows注册表的时候不能成功取出中文,插入的时候也不能插入中文
也就是,中文进去是乱码,中文出来也是乱码
崩溃了,从昨天晚上9点搞到今早3点,这编码解码问题我真是要抓狂了
朋友们帮我瞧瞧啊,不甚感激!!!

废话不多说,直接上代码
package available.registry.test;

import java.io.UnsupportedEncodingException;
import java.util.Enumeration;

import com.ice.jni.registry.NoSuchKeyException;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;
import com.ice.jni.registry.RegistryValue;

// 这个类使用了 registry.jar 中 jni 提供的功能!
public class RegistryManager {
public static void main(String[] args) throws NoSuchKeyException,
RegistryException {
// 提示如何在命令行下使用 registry.jar 文件,参数到底是什么意思?
// Registry.usage("123");

// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
RegistryKey registryKey = Registry.openSubkey(
Registry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\",
RegistryKey.ACCESS_READ);

// API 上声称返回的是一个 RegistryKey 类型的枚举,结果死活是String 类型的~
Enumeration<?> enums = registryKey.keyElements();
while (enums.hasMoreElements()) {
String subRKName = (String) enums.nextElement();
System.out.println("之前 " + subRKName);

subRKName = RegistryManager.make8859toGB(subRKName);
System.out.println("之后 " + subRKName);

RegistryKey sub = null;
try {
sub = registryKey.openSubKey(subRKName, RegistryKey.ACCESS_READ);
} catch (com.ice.jni.registry.NoSuchKeyException e) {
System.err.println("找不到这个键!");
}
if (sub != null) {
System.out.println("子键的名字为:" + sub.getName());
RegistryValue rv = sub.getValue("DisplayName");
if (rv != null) {
System.err.println(sub.getName()+" 子键 DisplayName 属性的值为:"+new String(rv.getByteData()));
System.out.println();
}
}
}
}

// iso-8859-1
public static String make8859toGB(String str) {
try {
// String str8859 = URLEncoder.encode(str, "Unicode");
// str8859 = URLDecoder.decode(str, "ASCII");
// String str8859 = URLDecoder.decode(str, "GBK");

// 从第二个参数的格式转换为第一个参数的格式~
 String str8859 = new String(str.getBytes("GBK"), "ASCII");
return str8859;
} catch (UnsupportedEncodingException ioe) {
ioe.printStackTrace();
}
return str;
}

}


报错信息为(我装了360杀毒和360安全卫士,中文死活显示为????):

之前 360SD
之后 360SD
子键的名字为:360SD
360SD 子键 DisplayName 属性的值为:360????

之前 360?????¦
之后 360??????W
找不到这个键!
之前 360????????
之后 360????????
之前 Adobe AIR
之后 Adobe AIR
子键的名字为:Adobe AIR
找不到这个键!

之前 Adobe Flash Player ActiveX
之后 Adobe Flash Player ActiveX
子键的名字为:Adobe Flash Player ActiveX
Adobe AIR 子键 DisplayName 属性的值为:Adobe AIR
Adobe Flash Player ActiveX 子键 DisplayName 属性的值为:Adobe Flash Player 10 ActiveX
之前 Adobe Flash Player Plugin
之后 Adobe Flash Player Plugin
子键的名字为:Adobe Flash Player Plugin

之前 Branding
之后 Branding
子键的名字为:Branding

Adobe Flash Player Plugin 子键 DisplayName 属性的值为:Adobe Flash Player 10 Plugin
Exception in thread "main" com.ice.jni.registry.NoSuchValueException: RegQueryValueEx(), value='DisplayName'
at com.ice.jni.registry.RegistryKey.getValue(Native Method)
at available.registry.test.RegistryManager.main(RegistryManager.java:44)

10 个解决方案

#1


神呐,来个人顶顶啊~

#2


应该就是编码的问题吧,

#3


引用 2 楼 wula0010 的回复:
应该就是编码的问题吧,

对啊,我也知道是编码的问题啊,哥们儿能不能帮我来看一下,我真的要抓狂了~~

#4


我上传了个dll文件.你替换一下,就可以正常显示中文了.
要传入中文参数应该还有问题.因为我也是参照网上的jni乱码修改的源代码strbufToJString方法.jStringToNewAscii方法修改编译不过去.有时间再弄了.
http://download.csdn.net/source/3182486

上面是dll下载.参照http://www.blogjava.net/mocci/archive/2005/12/08/22946.html的方法写的.

#5


楼上正解
之前也遇到过同样的问题,重新编译下那个dll就可以了

#6



/**
 * 将dll获取的字符串拼接回原来的形式.
 * 因为dll内以前的方法只是单纯的将byte复制到java的char里
 * if ( uniBuf != NULL )
{
for ( i = 0 ; i < len ; ++i )
uniBuf[i] = (jchar)  buf[i];
result = (*env)->NewString( env, uniBuf, (jsize)len );
free( uniBuf );
}
return result;

 * @param str 从dll获取的字符串
 * @return
 * @throws UnsupportedEncodingException
 */
static String decode(String str) throws UnsupportedEncodingException{
char[] charbuf = str.toCharArray();
     byte[] bytebuf = new byte[charbuf.length];
     for(int i=0;i<charbuf.length;i++){
     bytebuf[i] = (byte)charbuf[i];
     }
     return new String(bytebuf,"gbk");
}

/**
 * 相反要传入中文的字符来操作,需要修改中文为他所识别的乱码...即将中文按两字节一个,拆分开
 * @param str
 * @return
 * @throws UnsupportedEncodingException
 */
static String encode(String str) throws UnsupportedEncodingException{
byte[] bytebuf = str.getBytes("gbk");
char[] charbuf = new char[bytebuf.length];
for(int i=0;i<bytebuf.length;i++){
charbuf[i] = (char)bytebuf[i];
}
return new String(charbuf,0,charbuf.length);
}




 subRKName = encode( subRKName );//你看看结果.原理在上面.不用替换dll也可以

#7


就是把编码转换成字节了,楼主确认下是否有问题?

#8


引用 6 楼 qingralf 的回复:
Java code

/**
     * 将dll获取的字符串拼接回原来的形式.
     * 因为dll内以前的方法只是单纯的将byte复制到java的char里
     * if ( uniBuf != NULL )
        {
        for ( i = 0 ; i < len ; ++i )
            uniBuf[i] = (jchar)……

强!!终于解决了这个问题,是在是太感谢了!!

#9


引用 6 楼 qingralf 的回复:
Java code

/**
     * 将dll获取的字符串拼接回原来的形式.
     * 因为dll内以前的方法只是单纯的将byte复制到java的char里
     * if ( uniBuf != NULL )
        {
        for ( i = 0 ; i < len ; ++i )
            uniBuf[i] = (jchar)……

哥们儿这个decode 有点儿问题啊,我插不进去中文啊
我上代码,拜托给我看一下啊,不知不觉又整了几时~


public class CopyOfRegistryManager2 {
public static void main(String[] args) throws NoSuchKeyException,
RegistryException {
RegistryKey registryKey = Registry.openSubkey(
Registry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
RegistryKey.ACCESS_READ);

registryKey.createSubKey(RegistryUtil.decode("成功"), "");
}
}


跑到注册表里面一看,还是乱码 -- 
如果哥们儿百忙之中能够抽出一点空来的话,不妨帮我改下代码,我的需求很简单,从注册表中取出所有
安装程序的信息,
也就是遍历  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
的所有子键,取出每个子键的 DisplayName 属性打印出来(子键名有中文,子键的DisplayName属性也包含中文)
我把代码粘上吧
package available.registry.test;

import java.util.Enumeration;

import available.registry.basic.RegistryUtil;

import com.ice.jni.registry.NoSuchKeyException;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;
import com.ice.jni.registry.RegistryValue;

// 这个类使用了 registry.jar 中 jni 提供的功能!
public class RegistryManager {
private final Object o = new Object();
public static void main(String[] args) throws NoSuchKeyException,
RegistryException {
// 提示如何在命令行下使用 registry.jar 文件,参数到底是什么意思?
// Registry.usage("123");

// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
RegistryKey rootRK = Registry.openSubkey(
Registry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\",
RegistryKey.ACCESS_READ);
RegistryManager rm = new RegistryManager();

Enumeration<?> enums = rootRK.keyElements();
while (enums.hasMoreElements()) {
synchronized(rm.o) {
String childRKName = (String)enums.nextElement();
String childRKNameDecoded = RegistryUtil.decode(childRKName);
System.err.println("之后 " + childRKNameDecoded);

rm.getDisplayAttr(rootRK, childRKNameDecoded);
}
}
}

// “根键” 和 “枚举出来的子键名”
public synchronized void getDisplayAttr(RegistryKey rootRK, String childRKNameDecoded) throws NoSuchKeyException,
RegistryException {
RegistryKey childRK = null;
try {
childRK = rootRK.openSubKey(RegistryUtil.encode(childRKNameDecoded), RegistryKey.ACCESS_READ);
} catch (com.ice.jni.registry.NoSuchKeyException e) {
System.out.println(childRKNameDecoded + " 找不到这个键!");
}

if(childRK != null) {
// 获取子键的 DisplayName 属性的值
String subKeyName = RegistryUtil.decode(childRK.getName());

System.out.println("子键的名字为:" + subKeyName);
RegistryValue rv = null;
try {
rv = childRK.getValue("DisplayName");
} catch (com.ice.jni.registry.NoSuchValueException e) {
System.err.println("该子键没有这个 DisplayName 这个属性~");
}
if (rv != null) {
System.out.print(childRK.getName()+" 子键 DisplayName 属性的值为:");
String name = RegistryUtil.decode(new String(rv.getByteData()));
if(name == null) {
System.err.println("null");
} else if(name.equals("")) {
System.err.println("equals(\"\")");
} else {
System.err.println(name);
}
System.out.println();
}
}
}
}

#10


package available.registry.basic;

import java.io.UnsupportedEncodingException;

public class RegistryUtil {
/**
     * 将dll获取的字符串拼接回原来的形式.
     * 因为dll内以前的方法只是单纯的将byte复制到java的char里
     * if ( uniBuf != NULL )
        {
        for ( i = 0 ; i < len ; ++i )
            uniBuf[i] = (jchar)  buf[i];
        result = (*env)->NewString( env, uniBuf, (jsize)len );
        free( uniBuf );
        }
        return result;

     * @param str    从dll获取的字符串
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String decode(String str) {
     String result = null;
        char[] charbuf = str.toCharArray();
        byte[] bytebuf = new byte[charbuf.length];
        for(int i=0;i<charbuf.length;i++){
            bytebuf[i] = (byte)charbuf[i];
        }
        try {
         result = new String(bytebuf,"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
    }
    
    /**
     * 相反要传入中文的字符来操作,需要修改中文为他所识别的乱码...即将中文按两字节一个,拆分开
     * @param str
     * @return
     */
    public static String encode(String str) {
        byte[] bytebuf = null;
try {
bytebuf = str.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
        char[] charbuf = new char[bytebuf.length];
        for(int i=0;i<bytebuf.length;i++){
            charbuf[i] = (char)bytebuf[i];
        }
        return new String(charbuf,0,charbuf.length);
    }
}

#1


神呐,来个人顶顶啊~

#2


应该就是编码的问题吧,

#3


引用 2 楼 wula0010 的回复:
应该就是编码的问题吧,

对啊,我也知道是编码的问题啊,哥们儿能不能帮我来看一下,我真的要抓狂了~~

#4


我上传了个dll文件.你替换一下,就可以正常显示中文了.
要传入中文参数应该还有问题.因为我也是参照网上的jni乱码修改的源代码strbufToJString方法.jStringToNewAscii方法修改编译不过去.有时间再弄了.
http://download.csdn.net/source/3182486

上面是dll下载.参照http://www.blogjava.net/mocci/archive/2005/12/08/22946.html的方法写的.

#5


楼上正解
之前也遇到过同样的问题,重新编译下那个dll就可以了

#6



/**
 * 将dll获取的字符串拼接回原来的形式.
 * 因为dll内以前的方法只是单纯的将byte复制到java的char里
 * if ( uniBuf != NULL )
{
for ( i = 0 ; i < len ; ++i )
uniBuf[i] = (jchar)  buf[i];
result = (*env)->NewString( env, uniBuf, (jsize)len );
free( uniBuf );
}
return result;

 * @param str 从dll获取的字符串
 * @return
 * @throws UnsupportedEncodingException
 */
static String decode(String str) throws UnsupportedEncodingException{
char[] charbuf = str.toCharArray();
     byte[] bytebuf = new byte[charbuf.length];
     for(int i=0;i<charbuf.length;i++){
     bytebuf[i] = (byte)charbuf[i];
     }
     return new String(bytebuf,"gbk");
}

/**
 * 相反要传入中文的字符来操作,需要修改中文为他所识别的乱码...即将中文按两字节一个,拆分开
 * @param str
 * @return
 * @throws UnsupportedEncodingException
 */
static String encode(String str) throws UnsupportedEncodingException{
byte[] bytebuf = str.getBytes("gbk");
char[] charbuf = new char[bytebuf.length];
for(int i=0;i<bytebuf.length;i++){
charbuf[i] = (char)bytebuf[i];
}
return new String(charbuf,0,charbuf.length);
}




 subRKName = encode( subRKName );//你看看结果.原理在上面.不用替换dll也可以

#7


就是把编码转换成字节了,楼主确认下是否有问题?

#8


引用 6 楼 qingralf 的回复:
Java code

/**
     * 将dll获取的字符串拼接回原来的形式.
     * 因为dll内以前的方法只是单纯的将byte复制到java的char里
     * if ( uniBuf != NULL )
        {
        for ( i = 0 ; i < len ; ++i )
            uniBuf[i] = (jchar)……

强!!终于解决了这个问题,是在是太感谢了!!

#9


引用 6 楼 qingralf 的回复:
Java code

/**
     * 将dll获取的字符串拼接回原来的形式.
     * 因为dll内以前的方法只是单纯的将byte复制到java的char里
     * if ( uniBuf != NULL )
        {
        for ( i = 0 ; i < len ; ++i )
            uniBuf[i] = (jchar)……

哥们儿这个decode 有点儿问题啊,我插不进去中文啊
我上代码,拜托给我看一下啊,不知不觉又整了几时~


public class CopyOfRegistryManager2 {
public static void main(String[] args) throws NoSuchKeyException,
RegistryException {
RegistryKey registryKey = Registry.openSubkey(
Registry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
RegistryKey.ACCESS_READ);

registryKey.createSubKey(RegistryUtil.decode("成功"), "");
}
}


跑到注册表里面一看,还是乱码 -- 
如果哥们儿百忙之中能够抽出一点空来的话,不妨帮我改下代码,我的需求很简单,从注册表中取出所有
安装程序的信息,
也就是遍历  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
的所有子键,取出每个子键的 DisplayName 属性打印出来(子键名有中文,子键的DisplayName属性也包含中文)
我把代码粘上吧
package available.registry.test;

import java.util.Enumeration;

import available.registry.basic.RegistryUtil;

import com.ice.jni.registry.NoSuchKeyException;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;
import com.ice.jni.registry.RegistryValue;

// 这个类使用了 registry.jar 中 jni 提供的功能!
public class RegistryManager {
private final Object o = new Object();
public static void main(String[] args) throws NoSuchKeyException,
RegistryException {
// 提示如何在命令行下使用 registry.jar 文件,参数到底是什么意思?
// Registry.usage("123");

// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
RegistryKey rootRK = Registry.openSubkey(
Registry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\",
RegistryKey.ACCESS_READ);
RegistryManager rm = new RegistryManager();

Enumeration<?> enums = rootRK.keyElements();
while (enums.hasMoreElements()) {
synchronized(rm.o) {
String childRKName = (String)enums.nextElement();
String childRKNameDecoded = RegistryUtil.decode(childRKName);
System.err.println("之后 " + childRKNameDecoded);

rm.getDisplayAttr(rootRK, childRKNameDecoded);
}
}
}

// “根键” 和 “枚举出来的子键名”
public synchronized void getDisplayAttr(RegistryKey rootRK, String childRKNameDecoded) throws NoSuchKeyException,
RegistryException {
RegistryKey childRK = null;
try {
childRK = rootRK.openSubKey(RegistryUtil.encode(childRKNameDecoded), RegistryKey.ACCESS_READ);
} catch (com.ice.jni.registry.NoSuchKeyException e) {
System.out.println(childRKNameDecoded + " 找不到这个键!");
}

if(childRK != null) {
// 获取子键的 DisplayName 属性的值
String subKeyName = RegistryUtil.decode(childRK.getName());

System.out.println("子键的名字为:" + subKeyName);
RegistryValue rv = null;
try {
rv = childRK.getValue("DisplayName");
} catch (com.ice.jni.registry.NoSuchValueException e) {
System.err.println("该子键没有这个 DisplayName 这个属性~");
}
if (rv != null) {
System.out.print(childRK.getName()+" 子键 DisplayName 属性的值为:");
String name = RegistryUtil.decode(new String(rv.getByteData()));
if(name == null) {
System.err.println("null");
} else if(name.equals("")) {
System.err.println("equals(\"\")");
} else {
System.err.println(name);
}
System.out.println();
}
}
}
}

#10


package available.registry.basic;

import java.io.UnsupportedEncodingException;

public class RegistryUtil {
/**
     * 将dll获取的字符串拼接回原来的形式.
     * 因为dll内以前的方法只是单纯的将byte复制到java的char里
     * if ( uniBuf != NULL )
        {
        for ( i = 0 ; i < len ; ++i )
            uniBuf[i] = (jchar)  buf[i];
        result = (*env)->NewString( env, uniBuf, (jsize)len );
        free( uniBuf );
        }
        return result;

     * @param str    从dll获取的字符串
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String decode(String str) {
     String result = null;
        char[] charbuf = str.toCharArray();
        byte[] bytebuf = new byte[charbuf.length];
        for(int i=0;i<charbuf.length;i++){
            bytebuf[i] = (byte)charbuf[i];
        }
        try {
         result = new String(bytebuf,"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
    }
    
    /**
     * 相反要传入中文的字符来操作,需要修改中文为他所识别的乱码...即将中文按两字节一个,拆分开
     * @param str
     * @return
     */
    public static String encode(String str) {
        byte[] bytebuf = null;
try {
bytebuf = str.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
        char[] charbuf = new char[bytebuf.length];
        for(int i=0;i<bytebuf.length;i++){
            charbuf[i] = (char)bytebuf[i];
        }
        return new String(charbuf,0,charbuf.length);
    }
}