Dize UTF-8 bayt []


243

Diyelim ki BufferedInputStreamUTF-8 kodlu bir metin dosyasının baytlarını bir bayt dizisine okumak için a kullandım . Ben bir dizeye bayt dönüştürmek için aşağıdaki rutin kullanabilirsiniz biliyorum, ama bunu sadece baytlar yineleme ve her birini dönüştürmekten daha etkili / daha akıllı bir yolu var mı?

public String openFileToString(byte[] _bytes)
{
    String file_string = "";

    for(int i = 0; i < _bytes.length; i++)
    {
        file_string += (char)_bytes[i];
    }

    return file_string;    
}

17
Neden bunu yapamıyorsun String fileString = new String(_bytes,"UTF-8");?
CoolBeans

1
Alternatif olarak, bir char dizisine okumak için BufferedReader kullanabilirsiniz.
Andy Thomas


@CoolBeans Bunu bilseydim yapabilirdim;) Teşekkür ederim.
skeryl

Dosya boyutuna bağlı olarak, byte[]hafızanın tamamını yüklemek ve new String(_bytes,"UTF-8")(ya da hatta +=dizeyle parçalar tarafından) dönüştürmek en verimli olduğundan emin değilim . Zincirleme InputStreams ve Okuyucular, özellikle büyük dosyalarda daha iyi çalışabilir.
Bruno

Yanıtlar:


498

String için yapıcıya bakın

String str = new String(bytes, StandardCharsets.UTF_8);

Tembel hissediyorsanız , InputStream'i doğrudan bir String'e dönüştürmek için Apache Commons IO kütüphanesini kullanabilirsiniz:

String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

13
Veya Guava en Charsets.UTF_8 Eğer JDK üzerinde ise daha eski 1.7
siledh

6
Android API'sında 19'un altındaysanız Guava'nın Charsets.UTF_8'ini kullanın
Ben Clayton

Ve checkstyle şöyle diyorsa: "Yasadışı Örnekleme: java.lang.String örneğinden kaçınılmalıdır.", O zaman ne?
Attila Neparáczki

1
Burada java.nio.charset.Charset.availableCharsets()haritadaki tüm karakter kümelerini değil, tüm karakter kümelerini görebilirsiniz StandardCharsets. Ve başka bir karakter seti kullanmak ve hala String yapıcısının atmasını önlemek UnsupportedEncodingExceptionistiyorsanız kullanabilirsinizjava.nio.charset.Charset.forName()
nyxz

2
IOUtils.toString (inputStream, StandardCharsets.UTF_8) kullanımdan kaldırıldı.
Aung Myat Hein

41

Java String sınıfında, bayt dizisini dizeye dönüştürmek için yerleşik bir yapıcı vardır.

byte[] byteArray = new byte[] {87, 79, 87, 46, 46, 46};

String value = new String(byteArray, "UTF-8");

9

Utf-8 verilerini dönüştürmek için baytlar ve karakterler arasında 1-1 yazışma olduğunu varsayamazsınız. Bunu dene:

String file_string = new String(bytes, "UTF-8");

(Bah. Yanıtınızı Gönderin düğmesine basmanın yavaş olduğunu görüyorum.)

Dosyanın tamamını Dize olarak okumak için aşağıdakine benzer bir şey yapın:

public String openFileToString(String fileName) throws IOException
{
    InputStream is = new BufferedInputStream(new FileInputStream(fileName));

    try {
        InputStreamReader rdr = new InputStreamReader(is, "UTF-8");
        StringBuilder contents = new StringBuilder();
        char[] buff = new char[4096];
        int len = rdr.read(buff);
        while (len >= 0) {
            contents.append(buff, 0, len);
        }
        return buff.toString();
    } finally {
        try {
            is.close();
        } catch (Exception e) {
            // log error in closing the file
        }
    }
}

4

Bunun için yapıcıyı kullanabilirsiniz String(byte[] bytes) . Ayrıntılar için bu bağlantıya bakın. EDIT Ayrıca, plaka formunuzun varsayılan karakter setini java dokümanı uyarınca dikkate almanız gerekir:

Platformun varsayılan karakter kümesini kullanarak belirtilen bayt dizisinin kodunu çözerek yeni bir Dize oluşturur. Yeni String'in uzunluğu karakter kümesinin bir işlevidir ve bu nedenle bayt dizisinin uzunluğuna eşit olmayabilir. Varsayılan yapıcıda verilen baytlar geçerli olmadığında bu yapıcı davranışı belirtilmez. Kod çözme işlemi üzerinde daha fazla denetim gerektiğinde CharsetDecoder sınıfı kullanılmalıdır.


1
Baytlarınız platformun varsayılan karakter kümesinde değilse Charset, dönüşümün doğru olduğundan emin olmak için ikinci bağımsız değişkene sahip sürümü kullanabilirsiniz .
Mike Daniels

1
@MikeDaniels Gerçekten, tüm detayları dahil etmek istemedim. Cevabımı yeni düzenledim
GETah

2

Bu soruda açıklanan yöntemleri kullanabilirsiniz (özellikle bir InputStream ile başladığınız için): okuma / dönüştürme

Harici kütüphaneleri güvenmek istemiyorsanız Özellikle, deneyebileceğiniz bu cevabı okuyan, InputStreambir yoluyla InputStreamReaderbir içine char[]tampon ve içine ekler StringBuilder.


2

Bir UTF-8 bayt dizisiyle uğraştığınızı bilerek, kesinlikle bir charset adını kabul eden String yapıcısını kullanmak isteyeceksiniz . Aksi takdirde, kendinizi bazı kodlama tabanlı güvenlik açıklarına açık bırakabilirsiniz. Dikkat UnsupportedEncodingExceptionetmeniz gereken şeyi attığını unutmayın. Bunun gibi bir şey:

public String openFileToString(String fileName) {
    String file_string;
    try {
        file_string = new String(_bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // this should never happen because "UTF-8" is hard-coded.
        throw new IllegalStateException(e);
    }
    return file_string;
}

2

İşte bayt olarak okunacak ve bir dize yaratacak basitleştirilmiş bir fonksiyon. Muhtemelen dosyayı hangi kodlamanın içerdiğini bildiğinizi varsayar (ve aksi takdirde varsayılanlar).

static final int BUFF_SIZE = 2048;
static final String DEFAULT_ENCODING = "utf-8";

public static String readFileToString(String filePath, String encoding) throws IOException {

    if (encoding == null || encoding.length() == 0)
        encoding = DEFAULT_ENCODING;

    StringBuffer content = new StringBuffer();

    FileInputStream fis = new FileInputStream(new File(filePath));
    byte[] buffer = new byte[BUFF_SIZE];

    int bytesRead = 0;
    while ((bytesRead = fis.read(buffer)) != -1)
        content.append(new String(buffer, 0, bytesRead, encoding));

    fis.close();        
    return content.toString();
}

OP'nin sorusuyla eşleşmesi için varsayılanı utf-8 olacak şekilde düzenlenen kod.
scottt

1

String, byte [] ve charsetname parametrelerini alan bir kurucuya sahiptir :)


0

Bu aynı zamanda yinelemeyi de içerir, ancak bu çok çok maliyetli oldukları için dizeleri birleştirmekten çok daha iyidir.

public String openFileToString(String fileName)
{
    StringBuilder s = new StringBuilder(_bytes.length);

    for(int i = 0; i < _bytes.length; i++)
    {
        s.append((char)_bytes[i]);
    }

    return s.toString();    
}

8
sevgili efendim. String str = new String(byte[])iyi olacak.
zengr

3
Bu verimliliği artırır, ancak utf8 verilerinin kodunu düzgün çözmez.
Ted Hopp

0

Neden aradığınız şeyi elde edip bir bayt dizisi yerine dosyadan bir dize okuyamıyorsunuz? Gibi bir şey:

BufferedReader in = new BufferedReader(new InputStreamReader( new FileInputStream( "foo.txt"), Charset.forName( "UTF-8"));

daha sonra tamamlanana kadar inLine'ı okuyun.


Bazen, orijinal çizgi sınırlayıcılarını tutmak yararlı olabilir. OP bunu isteyebilir.
Bruno

0

Bu şekilde kullanıyorum

String strIn = new String(_bytes, 0, numBytes);


1
Bu bir karakter seti belirtmediğinden, UTF-8 olmayan platform varsayılan karakter setini elde edersiniz.
greg-449
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.