ห้องสมุดไหนที่จะใช้?
จากการเขียนนี้พวกเขาเป็นห้องสมุดสามแห่งที่ปรากฏ:
ฉันไม่ได้รวมApache Any23เพราะใช้ ICU4j 3.4 ภายใต้ประทุน
จะบอกได้อย่างไรว่าตัวใดตรวจจับชุดอักขระที่ถูกต้อง (หรือใกล้เคียงที่สุด)
เป็นไปไม่ได้ที่จะรับรองชุดอักขระที่ตรวจพบโดยแต่ละไลบรารีด้านบน อย่างไรก็ตามเป็นไปได้ที่จะขอให้พวกเขากลับมาและให้คะแนนการตอบกลับ
จะให้คะแนนการตอบกลับอย่างไร
การตอบสนองแต่ละครั้งสามารถกำหนดได้หนึ่งจุด ยิ่งมีการตอบสนองมากเท่าใดยิ่งมั่นใจชุดอักขระที่ตรวจพบก็จะยิ่งมากขึ้นเท่านั้น นี่เป็นวิธีการให้คะแนนแบบง่าย ๆ คุณสามารถทำอย่างละเอียดอื่น ๆ
มีรหัสตัวอย่างหรือไม่?
นี่คือข้อมูลโค้ดแบบสมบูรณ์ที่ใช้กลยุทธ์ที่อธิบายไว้ในบรรทัดก่อนหน้า
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() + " }";
}
การปรับปรุง:guessEncoding
วิธีการอ่าน InputStream ทั้งหมด สำหรับอินพุตขนาดใหญ่นี่อาจเป็นเรื่องกังวล ไลบรารีทั้งหมดเหล่านี้จะอ่านอินพุตทั้งหมด นี่จะเป็นการใช้เวลานานมากในการตรวจจับชุดอักขระ
เป็นไปได้ที่จะ จำกัด การโหลดข้อมูลเริ่มต้นเพียงไม่กี่ไบต์และทำการตรวจจับชุดอักขระบนสองสามไบต์เท่านั้น