Чтение и запись файлов с диакритическими знаками

У меня есть входной файл в формате XML, и он хорошо сформирован, с хорошо написанными акцентами. Файл создается с помощью PHP-скрипта, который отлично работает. Но когда я читаю файл XML и записываю его в другой XML с помощью программы Java, вместо символов с акцентами вставляются странные символы.

Это метод, который читает файл XML:

public static String getArchivo(FileInputStream fileinputstream)
{
    String s = null;
    try
    {
        byte abyte0[] = new byte[1024];
        int i = fileinputstream.read(abyte0);
        if(i != -1)
        {
            s = new String(abyte0, 0, i);
            for(int j = fileinputstream.read(abyte0); j != -1; j = fileinputstream.read(abyte0))
            {
                s = s + new String(abyte0, 0, j);
            }

        }
    }
    catch(IOException ioexception)
    {
        s = null;
    }
    return s;
}

Из-за того, что файл считывается побайтно, как заменить «плохие» байты на правильные байты для акцентированных символов? Если чтение таких файлов, как эти, байт за байтом, не является хорошей идеей, как я могу сделать это лучше?

Мне нужны следующие символы: á, é, í, ó, ú, Á, É, Í, Ó, Ú, ñ, Ñ и °.

заранее спасибо


person mrcoar    schedule 06.10.2015    source источник
comment
При чтении UTF (или любой многобайтовой кодировки символов) код сломается, несмотря ни на что, потому что он основан на преобразовании произвольно длинного массива байтов в char, что может разделить несколько байтов одного char по нескольким границам.   -  person GPI    schedule 06.10.2015
comment
В таком случае, как лучше всего это сделать?   -  person mrcoar    schedule 06.10.2015
comment
stackoverflow.com/q/28969941/2131074   -  person GPI    schedule 07.10.2015
comment
См. ссылку выше и ответ ниже. Обычно использование InputStreamReader, обертывающего ваш InputStream, и использование соответствующей кодировки - это путь. Внутренности считывателя будут правильно определять границы и избегать декодирования частичных символов, что может делать ваш текущий код.   -  person GPI    schedule 07.10.2015


Ответы (3)


Вероятно, вы читаете файл с кодировкой UTF-8. Специальные символы не являются частью кодировки UTF-8. Переход с UTF-8 на UTF-16

Что-то типа

InputStream in = ...
InputSource is = new InputSource(new InputStreamReader(in, "utf-16")); 

Как правильно сказал Джорди, за пределами utf-8 нет специальных символов. Поэтому рассматривайте первую часть как информацию для других специальных символов.

Глядя глубже на ваш код, я вижу, что вы читаете int и конвертируете его в строку. Не конвертируйте его. Прочитайте байты и запишите байты, чтобы убедиться, что данные не будут изменены.

person Davide Lorenzo MARINO    schedule 06.10.2015
comment
Специальные символы не являются частью UTF-8.... На самом деле гласные с наклоном не являются специальными символами и содержатся в диаграмма UTF8, насколько мне известно, весь испанский язык находится внутри UTF-8 - person Jordi Castilla; 06.10.2015
comment
@Jordi Да, я проверил, и запрошенные символы указаны в стандарте UTF-8, спасибо за ваше примечание, я не был уверен в символах тильды. - person Davide Lorenzo MARINO; 06.10.2015
comment
рад помочь @Davide, я знаю это, потому что я испанец :) - person Jordi Castilla; 06.10.2015
comment
Да, в Италии (я итальянец) у нас есть только некоторый акцент .... никаких акцентов с тильдой или циркумфлексами :) - person Davide Lorenzo MARINO; 06.10.2015
comment
Не согласен с этим решением: использование UTF16 возможно, хотя и маловероятно. Скорее всего, это файл UTF8 (или windows1252), а код OP ломается, потому что преобразование байта в символ выполняется в случайной точке входного потока. Однако использование Reader является хорошим предложением :-). Также велика вероятность, что если файл является действительным XML и передан в InputSource, базовый XML-движок выполнит правильное определение кодировки на основе пролога, что снизит необходимость знать или угадывать фактическую кодировку. - person GPI; 07.10.2015

У меня работает с Chaserset ISO 8859-1. Синтаксис в котлине:

val inputStream : InputStream = FileInputStream(filePath)
val json = inputStream.bufferedReader(Charsets.ISO_8859_1).use { it.readText()}
person Javier Hinmel    schedule 16.08.2019
comment
Спасибо, но это для Java 10, а я использую Java 8. - person mrcoar; 16.08.2019

Когда вы читаете файл, используйте кодировку utf-8 лучше всего

BufferedReader rd = new BufferedReader(new InputStreamReader(is, "utf-8"));

В письме также используйте utf-8

OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream(filePath, true), "utf-8");

Это сработало для меня.

При чтении файла в редакторе vi или другом редакторе измените кодировку по умолчанию на utf-8.

локаль charmap LANG=en_US.UTF-8

person Ravi Thapa    schedule 05.12.2017