Является ли символ 1 байтом или 2 байта в Java? - PullRequest
8 голосов
/ 13 мая 2011

Я думал, что символы в 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 с редактором иудалил не строковую часть, осталась только строка "abcd", которая в сумме составляет 4 байта.Кто-нибудь знает почему?Сохраняет ли Java автоматически пространство, используя ASCII вместо UNICODE для строк, которые могут поддерживаться ASCII?Спасибо

Ответы [ 5 ]

7 голосов
/ 13 мая 2011

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

Просто FYI, Unicode и UTF-8 - это не одно и то же. Юникод - это стандарт, который определяет, среди прочего, какие символы доступны. UTF-8 - это кодировка символов, которая определяет, как эти символы должны быть физически закодированы в 1 и 0. UTF-8 может использовать 1 байт для ASCII (<= 127) и до 4 байтов для представления других символов Юникода. </p>

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

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

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

2 голосов
/ 13 мая 2011

Да, 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();
        }
    }
1 голос
/ 13 мая 2011

Если вы посмотрите на источник String, он заметит, что он вызывает DataOutput.writeUTF для записи строк. И если вы прочитаете это, вы обнаружите, что они написаны как «модифицированный UTF-8». Детали длинны, но если вы не используете не 7-битную ASCII, да, это займет один байт. Если вы хотите узнать подробности, посмотрите на ОЧЕНЬ длинный Javadoc в DataOutput.writeUTF ()

0 голосов
/ 13 мая 2011

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

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

0 голосов
/ 13 мая 2011

Так вы ожидаете файл 16*4=64 bits = 8 bytes?Больше чем кодировка UTF-8 или ASCII.После того, как файл записан в файл.Управление памятью (с точки зрения пространства) зависит от операционной системы.И ваш код не имеет контроля над ним.

...