Sử dụng thư viện nào?
Theo văn bản này, chúng là ba thư viện xuất hiện:
Tôi không bao gồm Apache Any23 vì nó sử dụng ICU4j 3.4 dưới mui xe.
Làm thế nào để biết ai đã phát hiện bộ ký tự bên phải (hoặc càng gần càng tốt)?
Không thể xác nhận bộ ký tự được phát hiện bởi mỗi thư viện ở trên. Tuy nhiên, có thể lần lượt hỏi họ và cho điểm trả lời.
Làm thế nào để ghi điểm trả lời?
Mỗi phản hồi có thể được chỉ định một điểm. Phản hồi càng có nhiều điểm, bảng mã được phát hiện càng tự tin. Đây là một phương pháp tính điểm đơn giản. Bạn có thể xây dựng những người khác.
Có mã mẫu nào không?
Dưới đây là một đoạn đầy đủ thực hiện chiến lược được mô tả trong các dòng trước.
public static String guessEncoding(InputStream input) throws IOException {
// Load input data
long count = 0;
int n = 0, EOF = -1;
byte[] buffer = new byte[4096];
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((EOF != (n = input.read(buffer))) && (count <= Integer.MAX_VALUE)) {
output.write(buffer, 0, n);
count += n;
}
if (count > Integer.MAX_VALUE) {
throw new RuntimeException("Inputstream too large.");
}
byte[] data = output.toByteArray();
// Detect encoding
Map<String, int[]> encodingsScores = new HashMap<>();
// * GuessEncoding
updateEncodingsScores(encodingsScores, new CharsetToolkit(data).guessEncoding().displayName());
// * ICU4j
CharsetDetector charsetDetector = new CharsetDetector();
charsetDetector.setText(data);
charsetDetector.enableInputFilter(true);
CharsetMatch cm = charsetDetector.detect();
if (cm != null) {
updateEncodingsScores(encodingsScores, cm.getName());
}
// * juniversalchardset
UniversalDetector universalDetector = new UniversalDetector(null);
universalDetector.handleData(data, 0, data.length);
universalDetector.dataEnd();
String encodingName = universalDetector.getDetectedCharset();
if (encodingName != null) {
updateEncodingsScores(encodingsScores, encodingName);
}
// Find winning encoding
Map.Entry<String, int[]> maxEntry = null;
for (Map.Entry<String, int[]> e : encodingsScores.entrySet()) {
if (maxEntry == null || (e.getValue()[0] > maxEntry.getValue()[0])) {
maxEntry = e;
}
}
String winningEncoding = maxEntry.getKey();
//dumpEncodingsScores(encodingsScores);
return winningEncoding;
}
private static void updateEncodingsScores(Map<String, int[]> encodingsScores, String encoding) {
String encodingName = encoding.toLowerCase();
int[] encodingScore = encodingsScores.get(encodingName);
if (encodingScore == null) {
encodingsScores.put(encodingName, new int[] { 1 });
} else {
encodingScore[0]++;
}
}
private static void dumpEncodingsScores(Map<String, int[]> encodingsScores) {
System.out.println(toString(encodingsScores));
}
private static String toString(Map<String, int[]> encodingsScores) {
String GLUE = ", ";
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, int[]> e : encodingsScores.entrySet()) {
sb.append(e.getKey() + ":" + e.getValue()[0] + GLUE);
}
int len = sb.length();
sb.delete(len - GLUE.length(), len);
return "{ " + sb.toString() + " }";
}
Cải tiến:
CácguessEncoding
phương pháp đọc inputstream hoàn toàn. Đối với đầu vào lớn, điều này có thể là một mối quan tâm. Tất cả các thư viện sẽ đọc toàn bộ đầu vào. Điều này có nghĩa là tiêu thụ thời gian lớn để phát hiện bộ ký tự.
Có thể giới hạn tải dữ liệu ban đầu xuống một vài byte và chỉ thực hiện phát hiện bộ ký tự trên vài byte đó.