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

yang3wei 2011-04-11 02:29:26
用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)

...全文
338 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wula0010 2011-04-12
  • 打赏
  • 举报
回复
就是把编码转换成字节了,楼主确认下是否有问题?
qingralf 2011-04-12
  • 打赏
  • 举报
回复

/**
* 将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也可以
swoky 2011-04-12
  • 打赏
  • 举报
回复
楼上正解
之前也遇到过同样的问题,重新编译下那个dll就可以了
yang3wei 2011-04-12
  • 打赏
  • 举报
回复
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);
}
}
yang3wei 2011-04-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 qingralf 的回复:]
Java code

/**
* 将dll获取的字符串拼接回原来的形式.
* 因为dll内以前的方法只是单纯的将byte复制到java的char里
* if ( uniBuf != NULL )
{
for ( i = 0 ; i < len ; ++i )
uniBuf[i] = (jchar)……
[/Quote]
哥们儿这个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();
}
}
}
}
yang3wei 2011-04-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 qingralf 的回复:]
Java code

/**
* 将dll获取的字符串拼接回原来的形式.
* 因为dll内以前的方法只是单纯的将byte复制到java的char里
* if ( uniBuf != NULL )
{
for ( i = 0 ; i < len ; ++i )
uniBuf[i] = (jchar)……
[/Quote]
强!!终于解决了这个问题,是在是太感谢了!!
qingralf 2011-04-12
  • 打赏
  • 举报
回复
我上传了个dll文件.你替换一下,就可以正常显示中文了.
要传入中文参数应该还有问题.因为我也是参照网上的jni乱码修改的源代码strbufToJString方法.jStringToNewAscii方法修改编译不过去.有时间再弄了.
http://download.csdn.net/source/3182486

上面是dll下载.参照http://www.blogjava.net/mocci/archive/2005/12/08/22946.html的方法写的.
yang3wei 2011-04-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wula0010 的回复:]
应该就是编码的问题吧,
[/Quote]
对啊,我也知道是编码的问题啊,哥们儿能不能帮我来看一下,我真的要抓狂了~~
wula0010 2011-04-11
  • 打赏
  • 举报
回复
应该就是编码的问题吧,
yang3wei 2011-04-11
  • 打赏
  • 举报
回复
神呐,来个人顶顶啊~
网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的诊断和测试以及恢复系统功能的工具。小编的确一直都想把这方面的命令做个总结,这次辛苦老范给我们整理了这份实用的秘笈。   Bootcfg   bootcfg 命令启动配置和故障恢复(对于大多数计算机,即 boot.ini 文件)。   含有下列参数的 bootcfg 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 bootcfg 命令。   用法:   bootcfg /default  设置默认引导项。   bootcfg /add    向引导列表中添加 Windows 安装。   bootcfg /rebuild  重复全部 Windows 安装过程并允许用户选择要添加的内容。   注意:使用 bootcfg /rebuild 之前,应先通过 bootcfg /copy 命令备份 boot.ini 文件。   bootcfg /scan    扫描用于 Windows 安装的所有磁盘并显示结果。   注意:这些结果被静态存储,并用于本次会话。如果在本次会话期间磁盘配置发生变化,为获得更新的扫描,必须先重新启动计算机,然后再次扫描磁盘。   bootcfg /list   列出引导列表中已有的条目。   bootcfg /disableredirect 在启动引导程序中禁用重定向。   bootcfg /redirect [ PortBaudRrate] |[ useBiosSettings]   在启动引导程序中通过指定配置启用重定向。   范例: bootcfg /redirect com1 115200 bootcfg /redirect useBiosSettings   hkdsk   创建并显示磁盘的状态报告。Chkdsk 命令还可列出并纠正磁盘上的错误。   含有下列参数的 chkdsk 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 chkdsk 命令。   vol [drive:] [ chkdsk [drive:] [/p] [/r]   参数  无   如果不带任何参数,chkdsk 将显示当前驱动器中的磁盘状态。 drive: 指定要 chkdsk 检查的驱动器。 /p   即使驱动器不在 chkdsk 的检查范围内,也执行彻底检查。该参数不对驱动器做任何更改。 /r   找到坏扇区并恢复可读取的信息。隐含着 /p 参数。   注意 Chkdsk 命令需要 Autochk.exe 文件。如果不能在启动目录(默认为 %systemroot%System32)中找到该文件,将试着在 Windows 安装 CD 中找到它。如果有多引导系统的计算机,必须保证是在包含 Windows 的驱动器上使用该命令。 Diskpart   创建和删除硬盘驱动器上的分区。diskpart 命令仅在使用故障恢复控制台时才可用。   diskpart [ /add |/delete] [device_name |drive_name |partition_name] [size]   参数 无   如果不带任何参数,diskpart 命令将启动 diskpart 的 Windows 字符模式版本。   /add   创建新的分区。   /delete   删除现有分区。   device_name   要创建或删除分区的设备。设备名称可从 map 命令的输出获得。例如,设备名称:   DeviceHardDisk0   drive_name   以驱动器号表示的待删除分区。仅与 /delete 同时使用。以下是驱动器名称的范例:   D:   partition_name   以分区名称表示的待删除分区。可代替 drive_name 使用。仅与 /delete 同时使用。以下是分区名称的范例:   DeviceHardDisk0Partition1    大小   要创建的分区大小,以兆字节 (MB)表示。仅与 /add 同时使用。   范例   下例将删除分区: diskpart /delete Device HardDisk0 Partition3 diskpart /delete F:   下例将在硬盘上添加一个 20 MB 的分区:   diskpart /add Device HardDisk0 20   Fixboot

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧