SORU
17 Kasım 2009, Salı


Nasıl Varsayılan Java/Karakter kümesi Kodlaması Bulmak için?

Açık cevap Charset.defaultCharset() kullanmaktır ama yakın zamanda bu doğru cevabı olmayabilir. Sonuç gerçek karakter setini java tarafından kullanılan farklı olduğunu söylediler.çeşitli vesilelerle ıo sınıfları. Java gibi öntanımlı karakter kümesi 2 takım tutar. Herkes bu konuda herhangi bir anlayış var mı?

Bir vakada başarısız çoğaltmak mümkün. Kullanıcı hatası sayılır ama yine de tüm diğer sorunların kaynağı ortaya çıkabilir. İşte kodu

public class CharSetTest {

    public static void main(String[] args) {
    	System.out.println("Default Charset="   Charset.defaultCharset());
    	System.setProperty("file.encoding", "Latin-1");
    	System.out.println("file.encoding="   System.getProperty("file.encoding"));
    	System.out.println("Default Charset="   Charset.defaultCharset());
    	System.out.println("Default Charset in Use="   getDefaultCharSet());
    }

    private static String getDefaultCharSet() {
    	OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream());
    	String enc = writer.getEncoding();
    	return enc;
    }
}

Sunucumuz Latin-1 karakter setini biraz karışık kodlama (Latin-1/UTF-8 ANSI/) eski bir protokol ile uğraşmak gerekir. Tüm sunucularımız bu JVM parametresi ile çalıştırın

-Dfile.encoding=ISO-8859-1

Burada Java sonucu 5,

Default Charset=ISO-8859-1
file.encoding=Latin-1
Default Charset=UTF-8
Default Charset in Use=ISO8859_1

Birisi dosyayı ayarlayarak kodlama zamanı değiştirmeye çalışır.kodlama kod. Hepimiz bunun işe yaramayacağını biliyoruz. Ancak, bu görünüşte defaultCharset atar() ama gerçek varsayılan karakter kümesi OutputStreamWriter tarafından kullanılan etkilemez.

Bu hata veya bir özelliği var mı?

EDİT: kabul cevabı sorunun kök nedenini gösterir. Temelde, defaultCharset güven olmaz() varsayılan kodlama değil 5, I/O sınıfları tarafından kullanılan Java. Java 6 gibi görünüyor bu sorunu düzeltir.

CEVAP
17 Kasım 2009, Salı


Bu gerçekten garip... bir Kez ayarlandığında, varsayılan Karakter kümesi önbelleğe alınır ve sınıf bellekte ise değişmiş değil. System.setProperty("file.encoding", "Latin-1"); 12 *özelliği ayarı bir şey yapmaz. Her zaman Charset.defaultCharset() önbelleğe alınan karakter kümesi döndürür denir.

İşte benim sonuçlar:

Default Charset=ISO-8859-1
file.encoding=Latin-1
Default Charset=ISO-8859-1
Default Charset in Use=ISO8859_1

JVM 1.6 kullanıyorum.

(update)

Tamam. JVM 1.5 ile hata yeniden yaptım.

1.5, önbelleğe varsayılan karakter kümesi kaynak kodlarına göre ayarlı değil. Eğer bu bir hata ama 1.6 değişiklikler bu uygulama değil bilmiyorum ve önbelleğe alınan karakter kullanır:

JVM 1.5:

public static Charset defaultCharset() {
synchronized (Charset.class) {
    if (defaultCharset == null) {
	java.security.PrivilegedAction pa =
	    new GetPropertyAction("file.encoding");
	String csn = (String)AccessController.doPrivileged(pa);
	Charset cs = lookup(csn);
	if (cs != null)
	    return cs;
	return forName("UTF-8");
    }
    return defaultCharset;
}
}

JVM 1.6:

public static Charset defaultCharset() {
    if (defaultCharset == null) {
    synchronized (Charset.class) {
	java.security.PrivilegedAction pa =
	    new GetPropertyAction("file.encoding");
	String csn = (String)AccessController.doPrivileged(pa);
	Charset cs = lookup(csn);
	if (cs != null)
	    defaultCharset = cs;
            else 
	    defaultCharset = forName("UTF-8");
        }
}
return defaultCharset;
}

Zaman ayarlı dosya kodlama için file.encoding=Latin-1 gelecek sefer aramaya Charset.defaultCharset(), ne olur, çünkü önbelleğe öntanımlı karakter kümesi değil set olacak bulmaya uygun karakter adı Latin-1. Bu isim yanlış, çünkü buldum, değil mi, ve varsayılan UTF-8 döndürür.

OutputStreamWriter gibi IO sınıfları beklenmedik bir sonuç döndürmesi neden olarak
sun.nio.cs.StreamEncoder uygulanması (cadı bu IO sınıfları tarafından kullanılır) farklı olarak JVM, JVM 1.5 ve 1.6 için. JVM 1.6 uygulanması varsayılan bir IO sınıflar için sağlanan değilse kodlama için Charset.defaultCharset() yöntemi dayanır. JVM 1.5 uygulanması farklı bir yöntem Converters.getDefaultEncodingName(); öntanımlı karakter kümesi almak için kullanır. Bu yöntem, JVM başlatma sırasında ayarlanmış olan varsayılan karakter kümesi kendi önbelleği kullanır:

JVM 1.6:

   public static StreamEncoder forOutputStreamWriter(OutputStream out,
                                                     Object lock,
                                                     String charsetName)
       throws UnsupportedEncodingException
   {
       String csn = charsetName;
       if (csn == null)
           csn = Charset.defaultCharset().name();
       try {
           if (Charset.isSupported(csn))
               return new StreamEncoder(out, lock, Charset.forName(csn));
       } catch (IllegalCharsetNameException x) { }
       throw new UnsupportedEncodingException (csn);
   }

JVM 1.5:

public static StreamEncoder forOutputStreamWriter(OutputStream out,
					      Object lock,
					      String charsetName)
throws UnsupportedEncodingException
{
String csn = charsetName;
if (csn == null)
    csn = Converters.getDefaultEncodingName();
if (!Converters.isCached(Converters.CHAR_TO_BYTE, csn)) {
    try {
	if (Charset.isSupported(csn))
	    return new CharsetSE(out, lock, Charset.forName(csn));
    } catch (IllegalCharsetNameException x) { }
}
return new ConverterSE(out, lock, csn);
}

Ama yorumlara katılıyorum. Sanabu özelliği kullanan gerekmiyor. Uygulama ayrıntı.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • L- Crysis

    L- Crysis

    30 Aralık 2011
  • Miles Fisher

    Miles Fisher

    8 NİSAN 2009
  • Rockstar Games

    Rockstar Gam

    17 ŞUBAT 2006