程序在不知道encoding设置的情况下如何正确解读该文件呢?
根据讨论及个人理解,处理程序(如jspc)总是按ISO8859-1来读取输入文件,然后检查文件开始的几个字节(即Byte Order Mark,BOM,具体如何判断,可以参考Tomcat源码$SOURCE_DIR\jasper\jasper2\src\share\org\apache\jasper\xmlparser\XMLEncodingDetector.java的getEncodingName方法,在JSP Specification的Page Character Encoding一节也有详细论述)以探测文件是以何种格式保存的,当解析到encoding选项时,若encoding设置与文件实际保存格式不一致,会尝试进行转换,但这种转换可能在文件实际以ISO8859-1/UTF-8等单字节编码而encoding被设置成Unicode、UTF-16等双字节编码时发生错误。
JNI中文处理问题小结(2)
时间:2010-05-13 大卫的思维空间
下面重点讨论JNI中在C++程序与Java程序间进行数据传递时需要注意的问题。
在JNI中jstring采用的是UCS-2编码,与Java中String的编码方式一致。但是在C++中,字符串是用char(8位)或者wchar_t(16位,Unicode编码与jchar一致,但并非所有开发平台上都是Unicode编码,详见参考6),下面的程序证明了这一点(编译环境:VC6):
#include <iostream>
using namespace std;
int main()
{
locale loc( "Chinese-simplified" );
//locale loc( "chs" );
//locale loc( "ZHI" );
//locale loc( ".936" );
wcout.imbue( loc );
wcout << L"中文" << endl; //若没有L,会出问题
wchar_t wch[] = {0x4E2D, 0x6587, 0x0}; //"中文"二字的Unicode编码
wcout << wch << endl;
return 0;
}
JNI提供了几个方法来实现jstring与char/wchar_t之间的转换。jsize GetStringLength(jstring str)
const jchar *GetStringChars(jstring str, jboolean *isCopy)
void ReleaseStringChars(jstring str, const jchar *chars) 此外,为了便于以UTF-8方式进行传输、存储,JNI还提供了几个操作UTF格式的方法:jsize GetStringUTFLength(jstring str)
const char* GetStringUTFChars(jstring str, jboolean *isCopy)
void ReleaseStringUTFChars(jstring str, const char* chars) GetStringChars返回的是Unicode格式的编码串,而GetStringUTFChars返回的是UTF-8格式的编码串。要创建一个jstring,可以用如下方式:jstring NewJString( JNIEnv * env, LPCTSTR str )
{
if (!env || !str)
return 0;
int slen = strlen(str);
jchar * buffer = new jchar[slen];
int len = MultiByteToWideChar(CP_ACP, 0, str, strlen(str), buffer, slen);
if (len > 0 && len < slen)
buffer[len] = 0;
jstring js = env->NewString(buffer, len);
delete [] buffer;
return js;
} 而要将一个jstring对象转为一个char字符串数组,可以:int JStringToChar( JNIEnv * env, jstring str, LPTSTR desc, int desc_len )
{
int len = 0;
if (desc == NULL || str == NULL)
return -1;
// Check buffer size
if (env->GetStringLength(str) * 2 + 1 > desc_len)
{
return -2;
}
memset(desc, 0, desc_len);
const wchar_t * w_buffer = env->GetStringChars(str, 0);
len = WideCharToMultiByte(CP_ACP, 0, w_buffer, wcslen(w_buffer) + 1, desc, desc_len, NULL, NULL);
env->ReleaseStringChars(str, w_buffer);
if (len > 0 && len < desc_len)
desc[le |