файлы содержат нежелательные символы - PullRequest
0 голосов
/ 24 ноября 2018

У меня странная проблема в Java с символом спецификации <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, но не в первый раз, когда пишет заголовок.Есть идеи, как это решить ???

1 Ответ

0 голосов
/ 24 ноября 2018

UTF_16 не указывает порядок байтов, поэтому всегда создается метка порядка байтов, чтобы уточнить, какой порядок байтов записывается.

Из документации Charset :

В кодировках UTF-16 используются шестнадцатиразрядные величины, и поэтому они чувствительны к порядку байтов.В этих кодировках порядок байтов потока может указываться начальной меткой порядка байтов , представленной символом Unicode '\uFEFF'.Метки порядка байтов обрабатываются следующим образом:

  • При декодировании кодировки UTF-16BE и UTF-16LE интерпретируют начальные метки порядка байтов как ZERO-WIDTH NON-BREAKING SPACE;при кодировании они не пишут метки порядка байтов.
  • При декодировании кодировка UTF-16 интерпретирует метку порядка байтов в начале входного потока, чтобы указать порядок байтов потока, но по умолчаниюв big-endian, если нет метки порядка байтов; при кодировании используется порядок байтов с прямым порядком байтов и записывается метка порядка байтов с прямым порядком байтов.

(выделено мной). StandardCharsets.UTF_16 не указываетпорядок байтов, поэтому его кодировщик (который используется OutputStreamWriter) всегда записывает метку порядка байтов перед записью чего-либо еще.Чтобы подавить его, используйте взамен UTF_16BE или UTF_16LE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...