简体   繁体   English

如何修复ApplicationResources_fr.properties损坏

[英]How to fix ApplicationResources_fr.properties getting corrupted

I have a problem in a class I wrote. 我写的一堂课有问题。 The purpose of the class is to add/remove/update for the applicationResource.properties files which the <spring:message code="key" /> uses to provide bilingual support to the website. 该类的目的是为applicationResource.properties文件添加/删除/更新, <spring:message code="key" />用于为网站提供双语支持。 Manually interacting with the properties files works fine, but I had a greater need and so I built in a way to allow changes to be done from the database. 手动与属性文件交互可以很好地工作,但是我有一个更大的需求,因此我建立了一种允许从数据库中进行更改的方式。 This has given me a very dynamic and flexible system that I can work from. 这给了我一个非常动态和灵活的系统,我可以使用它。

However, there is a problem. 但是,有一个问题。 At some point after even a single change using this, the French characters end up getting changed. 甚至在使用此功能进行一次更改之后的某个时候,法语字符最终都会被更改。 Such as Déconnexion becoming Déconnexion . 例如Déconnexion成为Déconnexion When looked at in notepad++ its first Déconnexion and then corrupted to D\Ã\©connexion . 在notepad ++中查看时,它是第一个Déconnexion ,然后损坏为D\Ã\©connexion This example was part of the original properties file. 此示例是原始属性文件的一部分。

The original (not temp) properties files have the text file encoding set to other: UTF-8 . 原始(非临时)属性文件的text file encoding设置为other: UTF-8 The Project properties text file encoding is set to inherited from container (Cp1252) . 项目属性text file encoding设置为inherited from container (Cp1252) I tried changing to Other: UTF-8 with no change. 我尝试更改为“ Other: UTF-8 ,但没有更改。

So my question(s) is, what is causing the corruption to my French characters and how can I fix it? 所以我的问题是,是什么导致法语字符损坏,我该如何解决? I have provided the complete class below. 我在下面提供了完整的课程。

Update: After the assistance from StephaneM in her answer I was able to track down exactly what is causing the corruption, but have not fixed it yet. 更新:在StephaneM的回答帮助下,我能够准确找到导致损坏的原因,但尚未解决。 The loadProperties() function in the AR Class. AR类中的loadProperties()函数。 As soon as the temp AP files are loaded the French characters are corrupted. 临时AP文件一旦加载,法语字符就会损坏。 This makes me suspect the original process which creates the temp AP files is using a different encoding. 这使我怀疑创建临时AP文件的原始过程正在使用不同的编码。 So I will have to track it down. 因此,我将不得不对其进行跟踪。

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));
    }
}   

} }

Sample use case for the class, taken directly from application, but with some editing so only the relevant parts are here 该类的示例用例,直接取自应用程序,但进行了一些编辑,因此此处仅相关部分

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);

Regarding this question: "what is causing the corruption to my French characters and how can I fix it?", the answer is in the documentation ( Properties.store() ): 关于这个问题:“是什么导致我的法语字符损坏以及如何解决?”,答案在文档( Properties.store() )中:

public void store(OutputStream out, String comments) throws IOException 公共无效存储(OutputStream输出,字符串注释)抛出IOException

Writes this property list (key and element pairs) in this Properties table to the output stream in a format suitable for loading into a Properties table using the load(InputStream) method. 以适合于使用load(InputStream)方法加载到Properties表中的格式,将此Properties表中的此属性列表(键和元素对)写入输出流。

Properties from the defaults table of this Properties table (if any) are not written out by this method. 此方法不会写出此属性表的默认表中的属性(如果有)。

This method outputs the comments, properties keys and values in the same format as specified in store(Writer), with the following differences: 此方法以与store(Writer)中指定的格式相同的格式输出注释,属性键和值,但有以下区别:

  • The stream is written using the ISO 8859-1 character encoding. 使用ISO 8859-1字符编码写入流。
  • Characters not in Latin-1 in the comments are written as \\uxxxx for their appropriate unicode hexadecimal value xxxx. 注释中不在Latin-1中的字符将以其适当的Unicode十六进制值xxxx表示为\\ uxxxx。
  • Characters less than \ and characters greater than \~ in property keys or values are written as \\uxxxx for the appropriate hexadecimal value xxxx. 对于适当的十六进制值xxxx,属性键或值中小于\\ u0020的字符和大于\\ u007E的字符被写为\\ uxxxx。

I am not the only person who has faced this issue, I managed to find another question and it was one of the answers that lead me to my solution. 我不是唯一遇到此问题的人,我设法找到了另一个问题,这是引导我寻求解决方案的答案之一。 I have to thank another site for letting me know what to include. 我必须感谢另一个网站 ,让我知道要包含的内容。

There are only four added or changed lines, I will list them, and then give a complete function. 只有四行添加或更改,我将列出它们,然后给出完整的功能。

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();

The complete function 完整的功能

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();
    }
}

By introducing the reader and using that, it has cleared up French character corruption. 通过向读者介绍和使用它,它消除了法语字符的损坏。

I should mention that I changed every file property I could find over to UTF-8 before I did the above changes and got it working. 我应该提到的是,在进行上述更改并使其正常工作之前,我将可以找到的每个文件属性都更改为UTF-8。 This site gives you the changes I made. 站点为您提供了我所做的更改。 This was a nice page that helped me confirm the encodings. 这是一个不错的页面 ,可帮助我确认编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM