Как исправить испорченные ApplicationResources_fr.properties - PullRequest
0 голосов
/ 06 марта 2019

У меня проблема в классе, который я написал.Цель этого класса - добавить / удалить / обновить файлы applicationResource.properties, которые <spring:message code="key" /> использует для обеспечения двуязычной поддержки веб-сайта.Взаимодействие с файлами свойств вручную работает нормально, но у меня была большая потребность, и поэтому я построил таким образом, чтобы можно было вносить изменения из базы данных.Это дало мне очень динамичную и гибкую систему, с которой я могу работать.

Однако есть проблема.В какой-то момент после даже одного изменения с использованием этого, французские символы в конечном итоге меняются.Например, Déconnexion становится Déconnexion.При просмотре в блокноте ++ его сначала Déconnexion, а затем поврежден до D\u00C3\u00A9connexion.Этот пример был частью исходного файла свойств.

В исходных (не временных) файлах свойств для text file encoding установлено значение other: UTF-8.Свойства проекта text file encoding установлены на inherited from container (Cp1252).Я попытался изменить на Other: UTF-8 без изменений.

Итак, мой вопрос (-ы): что является причиной искажения моих французских символов и как я могу это исправить? Я предоставил полный класс ниже.

Обновление: После помощи StephaneM в ее ответе я смог точно выяснить, что является причиной повреждения, но пока не устранил его.Функция loadProperties () в классе AR.Как только файлы временного AP загружены, французские символы повреждены.Это заставляет меня подозревать, что оригинальный процесс, который создает временные AP-файлы, использует другую кодировку.Поэтому мне придется отследить его.

package pojo;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;

/*
 * Purpose of this class is to handle all the     ApplicationResource(_fr).properties interactions
 * so that there is one unified location handling this, instead of code duplication.
 */

public class AR{
public final String en_path = "/ApplicationResources.properties";
public final String fr_path = "/ApplicationResources_fr.properties";

private Properties en_prop = null;
private Properties fr_prop = null;

public AR()
{
    loadProperties();
}
private void loadProperties()
{
    InputStream en_is = null;
    InputStream fr_is = null;
    try {
        this.en_prop = new Properties();
        this.fr_prop = new Properties();
        en_is = this.getClass().getResourceAsStream(en_path);
        fr_is = this.getClass().getResourceAsStream(fr_path);
        en_prop.load(en_is);
        fr_prop.load(fr_is);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
private boolean keyExist(String mykey, String mypath)   //deprecated due to better code/method
{
    Properties test_prop = null;
        InputStream is = null;
        try {
            test_prop = new Properties();

            is = this.getClass().getResourceAsStream(mypath);
            test_prop.load(is);
            Set<Object> keys = test_prop.keySet();
            for(Object k:keys) {
                String key = (String)k;
                //System.out.print(key + " ");
                if(key.equals(mykey))   
                {
                    return true;
                }
            }
            //System.out.println(" ");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    return false;
}
public boolean en_keyExist(String mykey)
{
    //searches english file
    loadProperties();
    return en_prop.containsKey(mykey);
    //return keyExist(mykey, en_path);  //original method
}
public boolean fr_keyExist(String mykey)
{
    //searches french file
    loadProperties();
    return fr_prop.containsKey(mykey);
    //return keyExist(mykey, fr_path);  //original method
}
public boolean en_fr_keyExist(String mykey)
{
    //searches both english and french files
    loadProperties();
    return (en_prop.containsKey(mykey) && fr_prop.containsKey(mykey));
    //return (keyExist(mykey, en_path) && keyExist(mykey, fr_path));    //original method
}
public String en_returnProperty(String mykey)
{
    //returns null if key does not exist
    loadProperties();
    return this.en_prop.getProperty(mykey);
}
public String fr_returnProperty(String mykey)
{
    //returns null if key does not exist
    loadProperties();
    return this.fr_prop.getProperty(mykey);
}
public void appendProperty(Properties new_en_prop,Properties new_fr_prop)
{
    //note: during a test, setProperty (used in populating the properties) does not allow duplicates, it overwrites.
    //So, load the existing properties, and for each new property add it

    loadProperties();
    for(Object key : new_en_prop.keySet())
    {
        en_prop.setProperty((String)key, new_en_prop.getProperty((String)key));
    }
    try (OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);)
    {
        en_prop.store(en_os, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
    for(Object key : new_fr_prop.keySet())
    {
        fr_prop.setProperty((String)key, new_fr_prop.getProperty((String)key));
    }
    try (OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(),false);)
    {
        fr_prop.store(fr_os, null);
    } catch (IOException e) {
        e.printStackTrace();
    }

}
public boolean appendProperty(String mykey, String en_val, String fr_val)   //appears to have timing error due to only saving last value
//due to timing error this function is only suitable for single additions
//due to the timing error, tried returning boolean to have it finished but was not successful
//setting the class variables to static did not solve the timing issue
{
    loadProperties();
    en_prop.setProperty(mykey, en_val);
    try (OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);)
    {
        en_prop.store(en_os, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
    fr_prop.setProperty(mykey, fr_val);
    try (OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(),false);)
    {
        fr_prop.store(fr_os, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return true;

}
public void en_setProperty(String mykey, String en_val)
//suspected timing issue, use only for singular changes
{
    loadProperties();
    en_prop.setProperty(mykey, en_val);
    try (OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);)
    {
        en_prop.store(en_os, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public void fr_setProperty(String mykey, String fr_val)
//suspected timing issue, use only for singular changes
{
    loadProperties();
    fr_prop.setProperty(mykey, fr_val);
    try (OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(),false);)
    {
        fr_prop.store(fr_os, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public void compareResources()
{
    Properties new_en = new Properties();
    Properties new_fr = new Properties();

    for(Object key : en_prop.keySet())
    {
        new_en.setProperty((String)key, en_prop.getProperty((String)key));
    }
    for(Object key : fr_prop.keySet())
    {
        new_fr.setProperty((String)key, fr_prop.getProperty((String)key));
    }

    Properties temp = (Properties) new_en.clone();

    for(Object key : temp.keySet())
    {
        if(new_fr.containsKey((String) key))
        {
            new_fr.remove(key);
            new_en.remove(key);
        }
    }

    for(Object key : new_en.keySet())
    {
        System.out.println("English only key: " + ((String)key));
    }
    for(Object key : new_fr.keySet())
    {
        System.out.println("French only key: " + ((String)key));
    }
}   

}

Пример использования сценария для класса, взятый непосредственно из приложения, но с некоторым редактированием, поэтому здесь присутствуют только соответствующие части

AR testing = new AR();
Properties en_prop = new Properties();
Properties fr_prop = new Properties();

final String test_prod_cur = "{call BILINGUAL_VALUES(?)}";
ResultSet rs = null;
try     ( 
  Connection connection = jdbcTemplate.getDataSource().getConnection();
  CallableStatement callableStatement = connection.prepareCall(test_prod_cur);
)
{
    callableStatement.registerOutParameter(1, OracleTypes.CURSOR);
    callableStatement.executeUpdate();
    rs = (ResultSet) callableStatement.getObject(1);
    while (rs.next())
    {
        String thead = rs.getString(1);
        en_prop.setProperty(keyheader+thead, rs.getString(2));
        fr_prop.setProperty(keyheader+thead, rs.getString(3));
        //testing.appendProperty(keyheader+thead, rs.getString(2), rs.getString(3));    //has a timing issue, ends up only appending final value
   }
}
catch (SQLException e)
{
System.out.println("SQLException - bilingual values");
System.out.println(e.getMessage());
}       
testing.appendProperty(en_prop, fr_prop);

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Относительно этого вопроса: «что вызывает повреждение моих французских символов и как я могу это исправить?», Ответ находится в документации ( Properties.store () ):

публичное хранилище пустот (OutputStream out, Строка комментариев) выдает IOException

Записывает этот список свойств (пары ключей и элементов) в эти свойства таблица для выходного потока в формате, подходящем для загрузки в Таблица свойств с использованием метода load (InputStream).

Свойства из таблицы значений по умолчанию этой таблицы свойств (если есть) не выписаны этим методом.

Этот метод выводит комментарии, ключи свойств и значения в тот же формат, что указан в хранилище (Writer), со следующим различия:

  • Поток записывается с использованием кодировки символов ISO 8859-1.
  • Символы не в латинице-1 в комментариях пишутся как \ uxxxx для их соответствующего шестнадцатеричного значения Юникода xxxx.
  • Символы меньше \ u0020 и символы больше \ u007E в ключах или значениях свойств записываются как \ uxxxx для соответствующего шестнадцатеричного значения xxxx.
0 голосов
/ 18 марта 2019

Я не единственный, кто столкнулся с этой проблемой, мне удалось найти другой вопрос, и это был один из ответов , который привел меня к моему решению. Я должен поблагодарить еще один сайт , который дал мне знать, что включить.

Есть только четыре добавленные или измененные строки, я перечислю их, а затем предоставлю полную функцию.

import java.io.Reader;
Reader reader = new InputStreamReader(fr_is, "UTF-8");
fr_prop.load(reader); //instead of fr_prop.load(fr_is);
reader.close();

Полная функция

import java.io.Reader;

private void loadProperties()
{
    InputStream en_is = null;
    InputStream fr_is = null;
    try {
        this.en_prop = new Properties();
        this.fr_prop = new Properties();
        en_is = this.getClass().getResourceAsStream(en_path);
        fr_is = this.getClass().getResourceAsStream(fr_path);

        Reader reader = new InputStreamReader(fr_is, "UTF-8");

        en_prop.load(en_is);
        fr_prop.load(reader);
        reader.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Представив читателя и использовав его, он очистил французскую символьную коррупцию.

Я должен упомянуть, что я изменил каждое свойство файла, которое смог найти, на UTF-8, прежде чем вносить вышеуказанные изменения и заставить его работать. Этот сайт дает вам изменения, которые я сделал. Это была хорошая страница , которая помогла мне подтвердить кодировки.

...