import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.time.DateUtils;
public class MOFile {
/**
* string encoding
*/
private static final String UTF_8 = "UTF-8";
/**
* The file format revision of this MO file.
*/
public int fileFormatRevision;
/**
* The dictionary of the string and translated strings in this MO file.
*
* <p>
* The original strings are the keys ; the translated strings are the
* values.
* </p>
*/
public Map<String, String> strings;
/**
* The number of translations in this MO file.
*/
public int numStrings;
/**
* The project id and version in which this MO file is used.
*/
public String projectIdVersion;
/**
* Where to report bugs of msgid strings
*/
public String reportMsgidBugsTo;
/**
* The creation date of the PO template file that was used to create this MO
* file.
*/
public Date potCreationDate;
/**
* The creation date of the PO file that was used to create this MO file.
*/
public Date poRevisionDate;
/**
* The last translator who has worked on the translations of this MO file.
*/
public String lastTranslator;
/**
* The language team behind the translations of this MO file.
*/
public String languageTeam;
/**
* The mime version of this MO file, such as <code>1.0</code>
*/
public String mimeVersion;
/**
* The content type of this MO file, such as
* <code>text/plain; charset=UTF-8</code>
*/
public String contentType;
/**
* Constructor.
*/
public MOFile() {}
/**
* The content mime type of this MO file, such as <code>text/plain</code>.
*/
public String contentMimeType() {
return contentType.substring(0, contentType.indexOf(";"));
}
/**
* The charset of the content of this MO file, such as <code>UTF-8</code>.
*/
public String contentCharset() {
return contentType.substring(contentType.indexOf("=") + 1);
}
/**
* Value is usually <code>8bit</code>.
*/
public String contentTransferEncoding;
/**
* The raw plural forms as specified in the MO file, such as
* <code>nplurals=2; plural=n>1</code>.
*/
public String pluralForms;
/**
* The plural expression used in the MO file, to determine if a string is a
* plural form. The expression is usually <code>n>1</code>.
*/
public int plural() {
return Integer.valueOf(pluralForms.substring(pluralForms.lastIndexOf(">") + 1, pluralForms.lastIndexOf(";")));
}
/**
* The locale of this catalog.
*/
public String locale;
/**
* The plural value used in the MO file, to determine if a string is a
* plural form. The value is usually <code>2</code>.
*/
public int nPlural() {
return Integer.valueOf(pluralForms.substring(pluralForms.indexOf("=") + 1, pluralForms.indexOf(";")));
}
/**
* Parses the bytes representing a MO file.
*
* @param bytes
* The bytes of the MO file
* @return A MOFile instance containing the informations of the original .mo
* file.
* @throws Exception
*
* @throws GettextError
* if the bytes does not represent a valid MO file.
* @throws TypeError
* if the specified ByteArray is null.
*
*/
public static MOFile parseMOBytes(ByteBuffer bytes) throws Exception {
if (bytes == null) throw new IllegalArgumentException("The <bytes> parameter must not be null");
int originalPosition = bytes.position();
ByteOrder originalEndian = bytes.order();
int magicNumber = bytes.getInt();
if (magicNumber == 0xde120495) bytes.order(ByteOrder.LITTLE_ENDIAN);
else if (magicNumber == 0x950412de) bytes.order(ByteOrder.BIG_ENDIAN);
else throw new RuntimeException("The magic number is invalid.");
int fileFormatRevision = bytes.getInt();
if (fileFormatRevision > 0) throw new RuntimeException("Unknown or unsupported MO file format revision.");
int n = bytes.getInt();
if (n <= 0) throw new RuntimeException("The MO file has no translations.");
int o = bytes.getInt();
int t = bytes.getInt();
// skip 8 bytes
bytes.getInt();
bytes.getInt();
// Loop through string and translations location informations
// and retrieve string and translations infos
int LOOP_INCREMENT = 8;// 4+4
int NUM_LOOPS = n;// (n-1+1)
Map<String, String> dictionary = new HashMap<String, String>();
int i = -1;
int bytesIndent;
int strlen;
int stroffset;
int trStrlen;
int trStroffset;
while (++i < NUM_LOOPS) {
bytesIndent = i * LOOP_INCREMENT;
bytes.position(o + bytesIndent);
strlen = bytes.getInt();
stroffset = bytes.getInt();
bytes.position(t + bytesIndent);
trStrlen = bytes.getInt();
trStroffset = bytes.getInt();
// get string
bytes.position(stroffset);
byte[] dst = new byte[strlen];
bytes.get(dst);
String str = new String(dst, UTF_8);
bytes.position(trStroffset);
dst = new byte[trStrlen];
bytes.get(dst);
String trStr = new String(dst, UTF_8);
dictionary.put(str, trStr);
}
// The informations are assumed to be
// in the first string to be translated.
// The original string is empty
// We should be careful to check the evolution of it.
bytes.position(t);
int infolen = bytes.getInt();
int infooffset = bytes.getInt();
bytes.position(infooffset);
byte[] dst = new byte[infolen];
bytes.get(dst);
String infos = new String(dst, UTF_8);
String[] elements = infos.split("\n");
// Create and fill the MOFile instance
MOFile mo = new MOFile();
mo.fileFormatRevision = fileFormatRevision;
mo.strings = dictionary;
mo.numStrings = n;
mo.projectIdVersion = elements[0].substring(elements[0].indexOf(":") + 2);
mo.reportMsgidBugsTo = elements[1].substring(elements[1].indexOf(":") + 2);
try {
// YYYY-MM-DD HH::MM(+|-HHMM)
String rawPotCreationDate = elements[2].substring(elements[2].indexOf(":") + 2);
mo.potCreationDate = DateUtils.parseDate(rawPotCreationDate, new String[] { "yyyy-MM-dd HH:ssZ" });
String rawPoRevisionDate = elements[3].substring(elements[3].indexOf(":") + 2);
mo.poRevisionDate = DateUtils.parseDate(rawPoRevisionDate, new String[] { "yyyy-MM-dd HH:ssZ" });
} catch(Exception e) {
}
mo.lastTranslator = elements[4].substring(elements[4].indexOf(":") + 2);
mo.languageTeam = elements[5].substring(elements[5].indexOf(":") + 2);
mo.mimeVersion = elements[6].substring(elements[6].indexOf(":") + 2);
mo.contentType = elements[7].substring(elements[7].indexOf(":") + 2);
mo.contentTransferEncoding = elements[8].substring(elements[8].indexOf(":") + 2);
mo.pluralForms = elements[9].substring(elements[9].indexOf(":") + 2);
// Put the byte array in its original state.
bytes.position(originalPosition);
bytes.order(originalEndian);
return mo;
}
public static void main(String[] args) throws Exception {
File file = new File("E:\\data_i18n_v3.mo");
byte[] bytes = FileUtils.readFileToByteArray(file);
ByteBuffer buff = ByteBuffer.wrap(bytes);
MOFile mo = parseMOBytes(buff);
System.out.println(mo.projectIdVersion);
System.out.println(mo.numStrings);
}
}
.mo文件 读取类MOFile
最新推荐文章于 2022-02-19 21:18:23 发布