【原創】java讀取、更新國際化文件properties、json文件

國際化工具:properties屬性文件以及json文件的讀取、修改值內容、保存。
讀取和修改都是基於key-value的:方便理解和修改;具備properties文件<->json文件互相轉換的能力。
在實際項目中還用到properties屬性文件或json文件和excel文件的相互轉換的。
關於國際化,還需要考慮去重(一個詞條在系統中多種不同的翻譯會顯得很不專業,一個詞條重複翻譯浪費翻譯費用),考慮專業術語的維護,詞條的合理複用,不同語言的條目的一致性,字符寬度檢測(避免界面變形),語法的一致性等。

一、屬性文件properties的讀取、修改值內容、保存

package tool.i18n;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 屬性文件properties的讀取、修改值內容、保存
 * @author 陳小穩 csdn ID:ccxw1983
 *
 */
public class PropertyFileModify {

	public static void main(String[] args) throws IOException {
		String currentFilePath = "D:\\workspace123\\demo.json\\test_files\\unicode.properties";
		String saveFilePath = "D:\\workspace123\\demo.json\\test_files\\unicode_new.properties";
		HashMap<String, String> modifyKeyVals = new HashMap<String, String>();
		{
			modifyKeyVals.put("a.b.c", "newval");
		}
		modifyAndNewFile(currentFilePath, saveFilePath, modifyKeyVals,  "【有待翻譯】");
	}
	
	public static void modifyAndNewFile(String currentFilePath, String saveFilePath,
			HashMap<String, String> modifyKeyVals, String defaultVal) throws IOException {
		File file = new File(currentFilePath);
		ArrayList<String> lines = FileUtils2.readFile2Lines(file, FileUtils2.encoding);
		HashMap<String, String> currentMap = getCurrentKeyVals(lines);
		
		Boolean setDefaultVal = StringUtils.isNotBlank(defaultVal);
		if (currentMap.size() > modifyKeyVals.size()) {
			System.out.println("json文件key-val數目:" + currentMap.size() + "> 修改條目:" + modifyKeyVals.size());
			// 設置默認值
			if (setDefaultVal) {
				for (Iterator iterator = currentMap.keySet().iterator(); iterator.hasNext();) {
					String key = (String) iterator.next();
					if (!modifyKeyVals.containsKey(key)) {
						// System.out.println("沒有條目的翻譯:" + key);
						modifyKeyVals.put(key, defaultVal);
					}
				}
			}
		}

		// 修改文件
		StringBuffer newcontent = new StringBuffer();
		for (int i = 0; i < lines.size(); i++) {
			String line = StringUtils.trimToEmpty(lines.get(i));
			if (line.startsWith("#")) {
				newcontent.append(line);
				newcontent.append("\r\n");
				continue;
			} else {
				String[] keyvalarr = line.split("=");
				String key = StringUtils.trimToEmpty(keyvalarr[0]);
				if(modifyKeyVals.containsKey(key)){
					String val = modifyKeyVals.get(key);
					val = utf82unicode(val);
					newcontent.append(key);
					newcontent.append("=");
					newcontent.append(val);
					newcontent.append("\r\n");
				}else{
					newcontent.append(line);
					newcontent.append("\r\n");
				}				
			}
		}
		
		// 保存爲文件
		File newfile = new File(saveFilePath);
		if (newfile.exists()) {
			newfile.delete();
		}
		FileUtils.writeStringToFile(newfile, newcontent.toString(), "UTF-8");
	}

	private static HashMap<String, String> getCurrentKeyVals(ArrayList<String> lines) {
		HashMap<String, String> currentKeyVals = new HashMap<String, String>();
		for (int i = 0; i < lines.size(); i++) {
			String line = StringUtils.trimToEmpty(lines.get(i));
			if (line.startsWith("#")) {
				continue;
			} else {
				String[] keyvalarr = line.split("=");
				String key = StringUtils.trimToEmpty(keyvalarr[0]);
				String val = StringUtils.trimToEmpty(keyvalarr[1]);
				val = unicode2utf8(val);
				currentKeyVals.put(key, val);
			}
		}
		return currentKeyVals;
	}

	private static String utf82unicode(String val) {
		return Native2AsciiUtils.native2Ascii(val);
	}
	
	
	private static String unicode2utf8(String val) {
		return Native2AsciiUtils.ascii2Native(val);
	}

}

依賴的unicode轉碼工具類

轉自 https://blog.csdn.net/nospeak/article/details/83677030

package tool.i18n;

import java.io.IOException;

/**
 * native2ascii.exe Java code implementation.
 * @author https://blog.csdn.net/nospeak/article/details/83677030
 * @version 1.0
 */
public class Native2AsciiUtils {

	public static void main(String[] args) throws IOException {
		System.out.println(Native2AsciiUtils.ascii2Native("1\u4e2d 2\u56fd c"));
		System.out.println(Native2AsciiUtils.native2Ascii("1中 2國 c"));
	}

	/**
	 * prefix of ascii string of native character
	 */
	private static String PREFIX = "\\u";

	/**
	 * Native to ascii string. It's same as execut native2ascii.exe.<br>
	 * 和這個效果一致 native2ascii -encoding UTF-8 utf_8.txt unicode.properties
	 * 
	 * @param str
	 *            native string
	 * @return ascii string
	 */
	public static String native2Ascii(String str) {
		char[] chars = str.toCharArray();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < chars.length; i++) {
			sb.append(char2Ascii(chars[i]));
		}
		return sb.toString();
	}

	/**
	 * Native character to ascii string.<br>
	 * 和這個效果一致 native2ascii -reverse unicode.properties utf_8.txt
	 * @param c
	 *            native character
	 * @return ascii string
	 */
	private static String char2Ascii(char c) {
		if (c > 255) {
			StringBuffer sb = new StringBuffer();
			sb.append(PREFIX);
			int code = (c >> 8);
			String tmp = Integer.toHexString(code);
			if (tmp.length() == 1) {
				sb.append("0");
			}
			sb.append(tmp);
			code = (c & 0xFF);
			tmp = Integer.toHexString(code);
			if (tmp.length() == 1) {
				sb.append("0");
			}
			sb.append(tmp);
			return sb.toString();
		} else {
			return Character.toString(c);
		}
	}

	/**
	 * Ascii to native string. It's same as execut native2ascii.exe -reverse.
	 * 
	 * @param str
	 *            ascii string
	 * @return native string
	 */
	public static String ascii2Native(String str) {
		StringBuffer sb = new StringBuffer();
		int begin = 0;
		int index = str.indexOf(PREFIX);
		while (index != -1) {
			sb.append(str.substring(begin, index));
			sb.append(ascii2Char(str.substring(index, index + 6)));
			begin = index + 6;
			index = str.indexOf(PREFIX, begin);
		}
		sb.append(str.substring(begin));
		return sb.toString();
	}

	/**
	 * Ascii to native character.
	 * 
	 * @param str
	 *            ascii string
	 * @return native character
	 */
	private static char ascii2Char(String str) {
		if (str.length() != 6) {
			throw new IllegalArgumentException("Ascii string of a native character must be 6 character.");
		}
		if (!PREFIX.equals(str.substring(0, 2))) {
			throw new IllegalArgumentException("Ascii string of a native character must start with \"\\u\".");
		}
		String tmp = str.substring(2, 4);
		int code = Integer.parseInt(tmp, 16) << 8;
		tmp = str.substring(4, 6);
		code += Integer.parseInt(tmp, 16);
		return (char) code;
	}

}

PS:此工具類和使用native2ascii轉碼的一致,轉碼批處理腳本:

toUnicode.bat

REM UTF-8編碼的文件utf_8.txt  轉爲 unicode編碼的文件unicode.properties
REM 需要使用“ -encoding UTF-8”指定編碼否則會多輸出\ufffd等
REM 在 native2ascii 命令中 -encoding 指定的編碼爲(生成的)目標文件的編碼格式。
native2ascii -encoding UTF-8 utf_8.txt unicode.properties

toUtf8.bat

REM unicode編碼的文件 unicode.properties 轉成 utf-8的明文
REM native2ascii -reverse 命令中 -encoding 指定的編碼爲源文件的編碼格式。
native2ascii -reverse unicode.properties utf_8.txt

二、json類型的國際化資源串的讀取、修改、格式化、保存

package tool.i18n;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import net.sf.json.JSONObject;

/**
 * json文件的讀取、修改、格式化、保存
 * 
 * @author 陳小穩 csdn ID:ccxw1983
 *
 */
public class JsonFileModify {
	private File file;
	private String encoding = "UTF-8";
	// 用於修改
	private JSONObject jsonObject = null;

	public static void main(String[] args) throws IOException {
		// 當前 json文件
		String currentFilePath = "D:\\workspace123\\demo.json\\test_files\\1.json";
		
		// 待保存的 json文件
		String saveFilePath = "D:\\workspace123\\demo.json\\test_files\\new.json";
		
		// 待修改的key-val
		HashMap<String, String> modifyKeyVals = new HashMap<String, String>();
		{
			modifyKeyVals.put("bank1.attrs.attr2", "newval");
		}
		
		// 修改json文件內容 並保存爲新文件
		modifyAndNewFile(currentFilePath, saveFilePath, modifyKeyVals, "【有待翻譯】");
//		modifyAndNewFile(currentFilePath, saveFilePath, modifyKeyVals, null);
	}

	/**
	 * 修改json文件內容 並保存爲新文件
	 * 
	 * @param currentFilePath
	 *            當前 json文件
	 * @param saveFilePath
	 *            待保存的 json文件
	 * @param modifyKeyVals
	 *            待修改的key-val
	 * @param defaultVal
	 *            沒修改的key設置默認val
	 * @throws IOException
	 */
	public static void modifyAndNewFile(String currentFilePath, String saveFilePath,
			HashMap<String, String> modifyKeyVals, String defaultVal) throws IOException {
		// 讀取json文件信息
		JsonFileModify jsonFile = toJsonFile(currentFilePath);

		// 檢查是否所有都修改到了
		// 獲取當前 json文件的key-val
		HashMap<String, String> currentMap = jsonFile.getKeyValMap();

		Boolean setDefaultVal = StringUtils.isNotBlank(defaultVal);
		if (currentMap.size() > modifyKeyVals.size()) {
			System.out.println("json文件key-val數目:" + currentMap.size() + "> 修改條目:" + modifyKeyVals.size());
			// 設置默認值
			if (setDefaultVal) {
				for (Iterator iterator = currentMap.keySet().iterator(); iterator.hasNext();) {
					String key = (String) iterator.next();
					if (!modifyKeyVals.containsKey(key)) {
						// System.out.println("沒有條目的翻譯:" + key);
						modifyKeyVals.put(key, defaultVal);
					}
				}
			}
		}

		// 修改屬性
		for (Iterator iterator = modifyKeyVals.keySet().iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			String val = modifyKeyVals.get(key);
			jsonFile.modifyJsonValByKey(key, val);
		}

		// 輸出json字符串
		String formatJsonStr = jsonFile.toFormatJsonStr();
		// System.out.println(formatJsonStr);

		// 保存爲文件
		File newfile = new File(saveFilePath);
		if (newfile.exists()) {
			newfile.delete();
		}
		FileUtils.writeStringToFile(newfile, formatJsonStr, "UTF-8");
	}


	private HashMap<String, String> keyValMap = new HashMap<String, String>();
	
	/**
	 * 根據 json對象 獲取key-val
	 * 
	 * @return
	 */
	private HashMap<String, String> getKeyValMap() {
		this.keyValMap.clear();
		analysisJSONObject2keyVal(this.jsonObject, null);
		return this.keyValMap;
	}


	private void addToMap(String key, String val) {
		keyValMap.put(key, val);
		// System.out.println(key + "=" + val);
	}

	/**
	 * 解析 key-val,同時設置每對key-val的行號(從0開始,基於沒空白行且格式化的前提來推斷的行號)
	 * 
	 * @param obj
	 * @param keypath
	 */
	public void analysisJSONObject2keyVal(Object obj, String keypath) {
		if (obj instanceof String) {
			String key = keypath;
			String val = obj.toString();
			addToMap(key, val);
			// this.lineNumber++;
		} else if (obj instanceof JSONObject) {
			// 新的開始
			// this.lineNumber++;
			JSONObject jsonObject = (JSONObject) obj;
			for (Object iterable_element : jsonObject.keySet()) {
				String key = (String) iterable_element;
				Object childobj = jsonObject.get(key);
				String keychild = StringUtils.isBlank(keypath) ? key : keypath + "." + key;
				analysisJSONObject2keyVal(childobj, keychild);
			}
			// 結尾
			// this.lineNumber++;
		}
	}

	/**
	 * 根據json文件路徑初始化json文件修改類對象:確保文件存在,讀取json文件內容,轉成json對象
	 * 
	 * @param path
	 *            json文件路徑
	 * @return
	 * @throws IOException
	 */
	public static JsonFileModify toJsonFile(String path) throws IOException {
		File file = new File(path);
		if (!file.exists()) {
			throw new RuntimeException("file not exist: " + path);
		}
		JsonFileModify jsonFile = new JsonFileModify();
		jsonFile.setFile(file);
		jsonFile.init();
		return jsonFile;
	}

	/**
	 * 讀取json文件內容,轉成json對象
	 * 
	 * @throws IOException
	 */
	private void init() throws IOException {
		String content = FileUtils2.readFileContext(file, encoding);

		// 字符串 轉 json對象,參考:https://www.cnblogs.com/teach/p/5791029.html
		this.jsonObject = JSONObject.fromObject(content);
	}

	/**
	 * 轉成json字符串並格式化
	 */
	public String toFormatJsonStr() {
		// json對象 轉 json字符串
		String newjsonstr = this.jsonObject.toString();
		// 測試:格式化 json字符串
		newjsonstr = formatJsonStr(newjsonstr);
		// System.out.println(newjsonstr);
		return newjsonstr;
	}

	/**
	 * 格式化json字符串
	 * 
	 * @param newjsonstr
	 * @return
	 */
	public static String formatJsonStr(String newjsonstr) {
		newjsonstr = StringUtils.replace(newjsonstr, "{", "{\r\n");
		newjsonstr = StringUtils.replace(newjsonstr, "}", "\r\n}");
		newjsonstr = StringUtils.replace(newjsonstr, ",", ",\r\n");
//		newjsonstr = StringUtils.replaceAll(newjsonstr, "\\{", "\\{\r\n");
//		newjsonstr = StringUtils.replaceAll(newjsonstr, "\\}", "\r\n\\}");
//		newjsonstr = StringUtils.replaceAll(newjsonstr, ",", ",\r\n");
		String[] lines = newjsonstr.split("\r\n");
		int tcount = 0;
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < lines.length; i++) {
			String line = lines[i];
			if (line.startsWith("}") || line.endsWith("}")) {
				tcount--;
			}
			buffer.append(StringUtils.repeat("\t", tcount));
			buffer.append(line);
			buffer.append("\r\n");
			if (line.startsWith("{") || line.endsWith("{")) {
				tcount++;
			}
		}
		return buffer.toString();
	}

	/**
	 * 根據key修改 json對象 的值
	 * 
	 * @param keypath
	 * @param val
	 */
	public void modifyJsonValByKey(String keypath, Object val) {
		modifyJsonValByKey(this.jsonObject, keypath, val);
	}

	/**
	 * 修改json對象的屬性<br>
	 * JSONObject newjsonobj = modifyJson(jsonobj, "bank1.attrs.attr2",
	 * "newval");
	 * 
	 * @param jsonobj
	 *            json對象
	 * @param keypath
	 *            路徑,路徑間用.隔開
	 * @param val
	 *            內容值
	 * @return
	 */
	public static JSONObject modifyJsonValByKey(JSONObject jsonobj, String keypath, Object val) {
		String[] dirs = keypath.split("\\.");
		JSONObject tmp = jsonobj;
		String key = null;
		if (dirs.length > 1) {
			for (int i = 0; i < dirs.length - 1; i++) {
				key = dirs[i];
				tmp = (JSONObject) tmp.get(key);
			}
			key = dirs[dirs.length - 1];
		} else {
			key = keypath;
		}
		// 設置值
		tmp.element(key, val);
		return jsonobj;
	}



	public File getFile() {
		return file;
	}

	public void setFile(File file) {
		this.file = file;
	}
}

 

測試文件 D:\\workspace123\\demo.json\\test_files\\1.json

{
	"name":"cxw",
	"age":"37",
	"bank1":{
		"id":"bank1001",
		"money":"1",
		"attrs":{
			"attr1":"attr11",
			"attr2":"attr22"
		}
	},
	"bank2":{
		"id":"bank2002",
		"money":"2"
	}
}

測試文件 D:\\workspace123\\demo.json\\test_files\\unicode.properties

a.b.c=1\u4e2d 2\u56fd c
a.b.c1=1
a.b.c2=\u4e2d
a.b.c3=2
a.b.c4=\u56fd
a.b.c5=c
a.a.a=\u4e2d mm\u56fd nn

所需jar使用maven下載,pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>demo.json</groupId>
	<artifactId>demo.json</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>json demo</name>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.9</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-collections4</artifactId>
			<version>4.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-io</artifactId>
			<version>1.3.2</version>
		</dependency>


		<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
		<!-- <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> 
			<version>2.4</version> </dependency> -->
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<!-- https://maven.aliyun.com/mvn/view的central的 /net/sf/json-lib/json-lib/2.4/json-lib-2.4-jdk15.jar -->
			<classifier>jdk15</classifier>
		</dependency>

		<!-- https://mvnrepository.com/artifact/log4j/log4j -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>

	</dependencies>
</project>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章