как записать данные UTF8 в файл xml с помощью RandomAccessFile?

При попытке записать некоторые данные UTF8 в файл я получаю мусор в файле. Код выглядит следующим образом

public static boolean saveToFile(StringBuffer buffer,
                                   String fileName,
                                   ArrayList exceptionList,
                                   String className)
  {
    log.debug("In saveToFile for file [" + fileName + "]");

                RandomAccessFile raf = null;
                File file = new File(fileName);
                File backupFile = new File(fileName+"_bck");

                try
                {
                    if (file.exists())
                    {
                            if (backupFile.exists())
                            {
                            backupFile.delete();
                            }
                            file.renameTo(backupFile);
                    }
                    raf = new RandomAccessFile(file, "rw");
                    raf.writeBytes(buffer.toString());
                    raf.close();

Вывод buffer.toString():

<?xml version="1.0" encoding="UTF-8"?>
<ivr>
<version>1.1</version>
<templateName>αβγδεζη

Однако данные в файле

<?xml version="1.0" encoding="UTF-8"?>
<ivr>
<version>1.1</version>
<templateName>▒▒▒▒▒▒▒</templateName>

Как я могу убедиться, что данные в самом файле UTF8


person Manuj    schedule 24.07.2014    source источник
comment
Вы пробовали писать UTF, а не писать байты?   -  person JamesB    schedule 24.07.2014
comment
Я изменил сообщение, включив в него буфер и т. д. В основном буфер передается в функцию. Я уже распечатал вывод buffer.toString() в посте выше. Если я не уточнил ваш вопрос, пожалуйста, дайте мне знать   -  person Manuj    schedule 24.07.2014
comment
Я еще не пробовал писать UTF, хотя это в моем списке задач. Меня беспокоит то, что writeUTF (я где-то читал) writeUTF сначала записывает количество символов в файл, а затем символы. Кроме того, меня беспокоит другое: является ли writeUTF UTF8 или UTF16.   -  person Manuj    schedule 24.07.2014


Ответы (3)


Я не удивлен, что вы получаете мусор:

 raf.writeBytes(buffer.toString())

Документация для RandomAccessFile.writeBytes(String) говорит (выделение добавлено):

Записывает строку в файл в виде последовательности байтов. Каждый символ в строке записывается последовательно, путем отбрасывания старших восьми битов.

В некоторых случаях эта операция приведет к правильно закодированному файлу. Но в большинстве случаев это не так. Этот метод writeBytes() является глупым замыслом разработчиков Java. Вам нужно правильно закодировать текст как байты в UTF-8, а затем записать эти байты.

Вам действительно нужно работать с файлом как с файлом с произвольным доступом? Если нет, просто манипулируйте им с помощью Writer, обертывающего OutputStream.

Вы можете использовать Charset.encode(CharBuffer) для создания ByteBuffer, содержащего закодированные байты, затем запишите эти байты в файл:

 raf.write(StandardCharsets.UTF_8.encode(buffer).array());
person Raedwald    schedule 24.07.2014
comment
Да, обсуждая оффлайн в офисе, даже мы пришли к тому же выводу, что код нужно переделать, чтобы начать использовать что-то вроде OutputStream и т.п. - person Manuj; 24.07.2014

Javadoc для RandomAccessFile указывает, что для writeBytes()

Записывает строку в файл в виде последовательности байтов. Каждый символ в строке записывается последовательно, отбрасывая его старшие восемь битов. Запись начинается с текущей позиции указателя файла.

Предполагая, что отбрасывание частей вашей строки не является тем, что вам нужно, вы должны использовать writeUtf():

Записывает строку в файл, используя модифицированную кодировку UTF-8 машинно-независимым способом.

person Andrew Stubbs    schedule 24.07.2014
comment
Я попробую написатьUTF(), но только для эксперимента, так как теперь я более склонен использовать OutputStream и т. д. - person Manuj; 24.07.2014

person    schedule
comment
Можете ли вы добавить объяснение, что делает этот код и как он отвечает на вопрос? Ответы с небольшим объяснением обычно более полезны, чем просто код. - person Ljm Dullaart; 14.06.2021