我在Java中遇到一个奇怪的问题,它的BOM字符为<feff>
。我的代码基本上是从数据库读取一些数据并将其存储在JSONArray中,然后更改其格式以满足服务器所需的格式,最后将其写入文件。
这是当前存储数据的方式
SYSTEM_ROLE|INSTITUTION_ROLE|ROW_STATUS|AVAILABLE_IND|EXTERNAL_PERSON_KEY|USER_ID|PASSWD|TITLE|FIRSTNAME|LASTNAME|GENDER|COUNTRY|CITY|EMAIL|H_PHONE_1|M_PHONE|BIRTHDATE|JOB_TITLE|STUDENT_ID
<feff>none|P_Unified_Program|Enabled|Y|xxxxxx@xxxxxx|xxxxxx|xxxxxx|Mr.|xxxxxx|xxxxxx|M|xxxxxx|xxxxxx (xxxxxx|xxxxxx@xxxxxx|xxxxxx|xxxxxx|05/07/2000|(xxxxxx|xxxxxx
none|P_Unified_Program|Enabled|Y|xxxxxx@xxxxxx|xxxxxx|xxxxxx|Mr.|xxxxxx|xxxxxx|M|xxxxxx|xxxxxx (xxxxxx)|xxxxxx@xxxxxx|xxxxxx|xxxxxx|xxxxxx|(xxxxxx|xxxxxx
注意第二行的字符。奇怪的是,那个字符没有出现在第一行。
这就是我写数据以匹配服务器所需格式的方式
public static String rawDBformat(JSONArray json, String[] columnsnames) {
if (json.length() == 0 || columnsnames.length == 0) {
logger.error("either the jsons' or the arrays' length passed to internaltoDBformat equal to zero " + json.toString());
throw new IllegalArgumentException("either the strings' or the arrays' length passed to toDBformat equal to zero");
}
int numberofcolumns = columnsnames.length;
String temp = "";
String res = "";
JSONObject jsonobj=null;
jsonobj = json.getJSONObject(0);
temp = jsonobj.getString(columnsnames[0]);
for (int j = 1; j < numberofcolumns; j++) {
temp += '|' + jsonobj.getString(columnsnames[j]);
}
res += temp + "\n";
for (int i = 0; i < json.length(); i++) {
jsonobj = json.getJSONObject(i);
temp = jsonobj.getString(columnsnames[0]);
for (int j = 1; j < numberofcolumns; j++) {
temp += '|' + jsonobj.getString(columnsnames[j]);
}
res += temp + "\n";
}
return res;
}
这就是我写文件的方式
public static void writetofile(File file, String data) throws
IOException {
OutputStreamWriter outputstream = null;
FileOutputStream fos = null;
try {
logger.info("writing some data to " +
file.getCanonicalPath());
fos = new FileOutputStream(file, true);
outputstream = new
OutputStreamWriter(fos,StandardCharsets.UTF_16);
outputstream.write(data);
fos.flush();
outputstream.flush();
} catch (Exception ex) {
logger.error("An Exception occared", ex);
} finally {
try {
fos.close();
outputstream.close();
} catch (Exception ex) {
logger.error("An Exception occared", ex);
}
}
}
这是两者的用法
writetofile(assign, rawDBformat(res.json, res.columnsNames));
assign
是文件,res.json
是JSONArray,res.columnsNames
是字符串数组。
一开始我以为char是在rawDBformat函数中添加的,所以我尝试了return res.substring(1);
,但是那没有用,结果是返回缺少第一个char的原始数据。我还注意到,每次调用writetofile
时都会添加char,但不是第一次写入标头。任何想法如何解决这个问题?
答案 0 :(得分:0)
UTF_16没有指定字节顺序,因此始终会生成一个字节顺序标记来阐明正在写入哪个字节顺序。
UTF-16字符集使用16位数字,因此对字节顺序敏感。在这些编码中,流的字节顺序可以由以Unicode字符
'\uFEFF'
表示的初始字节顺序标记表示。字节顺序标记的处理方式如下:
- 解码时,
UTF-16BE
和UTF-16LE
字符集将初始字节顺序标记解释为ZERO-WIDTH NON-BREAKING SPACE
;编码时,它们不会写字节顺序标记。- 在解码时,
UTF-16
字符集解释输入流开头的字节顺序标记以指示流的字节顺序,但是如果没有字节顺序标记,则默认为big-endian; 编码时,它使用大端字节序并写入一个大端字节序标记。
(强调我的。)StandardCharsets.UTF_16没有指定字节顺序,因此其编码器(由OutputStreamWriter使用)始终在写入其他内容之前先写入字节顺序标记。要抑制它,请改用UTF_16BE或UTF_16LE。