文件包含不需要的字符

时间:2018-11-23 22:28:31

标签: java file

我在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,但不是第一次写入标头。任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

UTF_16没有指定字节顺序,因此始终会生成一个字节顺序标记来阐明正在写入哪个字节顺序。

来自documentation of Charset

  

UTF-16字符集使用16位数字,因此对字节顺序敏感。在这些编码中,流的字节顺序可以由以Unicode字符'\uFEFF'表示的初始字节顺序标记表示。字节顺序标记的处理方式如下:

     
      
  • 解码时,UTF-16BEUTF-16LE字符集将初始字节顺序标记解释为ZERO-WIDTH NON-BREAKING SPACE;编码时,它们不会写字节顺序标记。
  •   
  • 在解码时,UTF-16字符集解释输入流开头的字节顺序标记以指示流的字节顺序,但是如果没有字节顺序标记,则默认为big-endian; 编码时,它使用大端字节序并写入一个大端字节序标记。
  •   

(强调我的。)StandardCharsets.UTF_16没有指定字节顺序,因此其编码器(由OutputStreamWriter使用)始终在写入其他内容之前先写入字节顺序标记。要抑制它,请改用UTF_16BE或UTF_16LE。