第六代禁片:quercus 数据库中文乱码问题研究, 解决了.
1.给mysql加上详细日志,以便分析问题所在
修改my.ini ,在文件最后加一行
log=mysql.log.txt
重启mysql server, 只要有SQL执行,就会生成一个日志文件 mysql.log.txt ,在data 目录中.
2.在quercus 中执行PHP,做一次mysql_connect , 再查看mysql.log.txt日志
SET NAMES latin1
这就是问题所在.
3.去quercus源代码目录里搜索: 'latin1'
Mysqli.java(228):
可能就是关键!
4. 修改源码, 干掉bug.
经测试,
将这两个文件的 latin1 改为 utf8.
编译,更新相关文件 .
问题解决了! done!
5.测试
the php code:
the mysql database :
用户282 , "用户"这个中文终于正确了.
6.下一步. 续集:
到目前为止, 暂时只解决了写入mysql时中文正常.
从mysql读出时,还有问题. 估计问题在于:
\src\com\caucho\quercus\lib\db\MysqliResult.java (约 line 990 )
2011-03-24 ,花了一上午的时候研究,发现问题果然在这里, 并且已经搞定了.
将MysqliResult.java 文件line 934开始的 getColumnString函数修改为如下的内容:
意思大概是在返回数据之前的,处理编码问题
[code]
protected Value getColumnString(Env env, ResultSet rs,
ResultSetMetaData md, int column) throws SQLException {
// php/1464, php/144f, php/144g, php/144b
// The "SET NAMES 'latin1'" in Mysqli is important to make the default
// encoding sane
Mysqli mysqli = getMysqli();
if (rs instanceof QuercusResultSet) {
QuercusResultSet qRs = (QuercusResultSet) rs;
int length = qRs.getStringLength(column);
if (length < 0)
return NullValue.NULL;
// XXX: i18n
StringBuilderValue sb = new StringBuilderValue();
sb.ensureAppendCapacity(length);
qRs.getString(column, sb.getBuffer(), sb.getOffset());
sb.setOffset(sb.getOffset() + length);
return sb;
}
Method getColumnCharacterSetMethod = mysqli
.getColumnCharacterSetMethod(md.getClass());
String encoding = null;
try {
if (getColumnCharacterSetMethod != null)
encoding = (String) getColumnCharacterSetMethod.invoke(md,
column);
} catch (Exception e) {
log.log(Level.FINE, e.toString(), e);
}
// calling getString() will decode using the database encoding, so
// get bytes directly. Also, getBytes is faster for MySQL since
// getString converts from bytes to string.
byte[] bytes = rs.getBytes(column);
if (bytes == null)
return NullValue.NULL;
StringValue bb = env.createUnicodeBuilder();
String value = null;
try {
value = new String(bytes, "UTF8");
//System.out.println(value);
bb.append(value.getBytes("UTF8"));
//System.out.println(bb);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bb;
}
[/code]
good, 到这里 quercus操作mysql的乱码问题,圆满解决了.
value = new String(bytes, "UTF8");
bb.append(value.getBytes("UTF8"));
这里要来两次, 原因我也不清楚, 我是试误试出来的. 本人PHP算得上精通, java只知道个皮毛, 将就能用就行了.
另: 再一步, 搞定eval的中文乱码问题.
想法大约是修改eval函数的实现: 在eval函数体的第一行, 加入几句,把传进来的参数, 编码给转换回去.