Символ 1 байт или 2 байта в Java?

Я думал, что символы в java-это 16 бит, как предложено в java doc. Разве дело не в струнах? У меня есть код, который хранит объект в файле:

public static void storeNormalObj(File outFile, Object obj) {
    FileOutputStream fos = null;
    ObjectOutputStream oos = null;
    try {
        fos = new FileOutputStream(outFile);
        oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);
        oos.flush();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            oos.close();
            try {
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

в основном, я пытался сохранить строку "abcd" в файле "output", когда я открыл output С редактором и удалил строковую часть none, что осталось только строка "abcd", которая составляет 4 байта в общей сложности. Кто-нибудь знает почему? Java автоматически экономит место, используя ASCII вместо UNICODE для строк, которые могут поддерживаться ASCII? Спасибо

5 ответов


(Я думаю, что "нет Строковой части" вы имеете в виду байты, которые ObjectOutputStream испускает при его создании. Возможно, вы не хотите использовать ObjectOutputStream, но я не знаю ваших требований.)

просто FYI, Unicode и UTF-8-это не одно и то же. Юникод-это стандарт, который определяет, среди прочего, какие символы доступны. UTF-8-это кодировка символов, которая определяет, как эти символы должны быть физически закодированы в 1s и 0s. UTF-8 может использовать 1 байт для ASCII (

UTF-8 является строгим надмножеством ASCII. Поэтому, даже если вы укажете кодировку UTF-8 для файла и запишете в него "abcd", он будет содержать только эти четыре байта: они имеют ту же физическую кодировку в ASCII, что и в UTF-8.

ваш метод использует ObjectOutputStream который на самом деле имеет значительно отличную кодировку, чем ASCII или UTF-8! Если вы внимательно читаете Javadoc, если obj это строка и уже произошла в потоке, последующие вызовы writeObject вызовет ссылку на предыдущую строку, которая может привести к тому, что в случае повторяющихся строк будет записано гораздо меньше байтов.

Если вы серьезно относитесь к пониманию этого, вы действительно должны потратить много времени на чтение о Unicode и системах кодирования символов. Википедия имеет отличную статью о Unicode как начать.


Да,char - Это только Unicode в контексте среды выполнения Java. Если вы хотите написать его с помощью 16-битной кодировки, используйте FileWriter.

    FileWriter outputStream = null;

    try {
        outputStream = new FileWriter("myfilename.dat");

        int c;
        while ((c = inputStream.read()) != -1) {
            outputStream.write(c);
        }
    } finally {
        if (outputStream != null) {
            outputStream.close();
        }
    }

Если вы посмотрите на источник строки, он заметит, что он вызывает DataOutput.writeUTF для записи строк. И если вы прочитаете это, вы узнаете, что они написаны как "модифицированный UTF-8". Детали длинны, но если вы не используете не 7 бит ascii, да, это займет один байт. Если вы хотите, чтобы кровавые детали смотрели на чрезвычайно длинный javadoc в DataOutput.writeUTF()


вам может быть интересно узнать, что есть -XX:+UseCompressedStrings опция в выпуске производительности Java Update 21 и позже. Это позволит String использовать byte[] для строк, которые не нужны char[]

несмотря на параметры Java Hotspot VM руководство, предполагающее, что он может быть включен по умолчанию, это может быть только для выпусков производительности. Он работает только для меня, если я включаю его явно.


Так вы ожидаете ? Больше, чем кодировка UTF-8 или ASCII. Как только файл записывается в файл. Управление памятью (с точки зрения пространства) зависит от операционной системы. И ваш код не имеет контроля над этим.