Вопрос SAXParseException (как вырезать любые символы спецификации из файла xml) - PullRequest
0 голосов
/ 11 февраля 2020

У меня есть некоторые данные в файле xml, и я использую библиотеку Process для анализа этого файла. Я столкнулся с проблемой маркера BOM , которая вызвала некоторые ошибки. Я нашел работу в другом месте, которая очень медленная: я использую Apache Commons BOMInputStream, чтобы прочитать файл как набор байтов, после пропуска тех, которые представляют эти данные спецификации.

Я думаю, что источником моей проблемы на самом деле является отсутствие у меня знаний о потоках, читателях и писателях. Есть столько разных читателей и писателей и всевозможных «потоков» (слово, которое я едва понимаю), которое я хочу вырвать, пытаясь понять, какой из них использовать и как. Я думаю, что я просто выбрал неправильную реализацию.

Вопрос: Может кто-нибудь показать мне, почему мой код такой медленный, а также помочь мне лучше понять файловый ввод / вывод?

Код:

private static XML noBOM(String filename, PApplet p) throws FileNotFoundException, IOException{

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    File f = new File(filename);
    InputStream stream = new FileInputStream(f);
    BOMInputStream bomIn = new BOMInputStream(stream);

    int tmp = -1;
    while ((tmp = bomIn.read()) != -1){
        out.write(tmp);
    }

    String strXml = out.toString();
    return p.parseXML(strXml);
}

public static Map<String, Float> lifeExpectancyFromXML(String filename, PApplet p, 
        int year) throws FileNotFoundException, IOException{


    Map<String, Float> dataMap = new HashMap<>();

    XML xml = noBOM(filename, p);

    if(xml != null){

        XML[] records = xml.getChild("data").getChildren("record");

        for (XML record : records){
            XML[] fields = record.getChildren("field");

            String country = fields[0].getContent();
            int entryYear = fields[2].getIntContent();
            float lifeEx = fields[3].getFloatContent();

            if (entryYear == year){
                System.out.println("Country: " + country);
                System.out.println("Life Expectency: " + lifeEx);
                dataMap.put(country, lifeEx);
            }
        }
    } 
    else {
        System.out.println("String could not be parsed.");
    }

    return dataMap;
} 

Ответы [ 2 ]

0 голосов
/ 11 февраля 2020

Мое решение состояло в том, чтобы использовать BufferedReader вместо создания моего собственного буфера. Это сделало все довольно быстро:

private static XML noBOM(String path, PApplet p) throws 
            FileNotFoundException, UnsupportedEncodingException, IOException{

        //set default encoding
        String defaultEncoding = "UTF-8";

        //create BOMInputStream to get rid of any Byte Order Mark
        BOMInputStream bomIn = new BOMInputStream(new FileInputStream(path));

        //If BOM is present, determine encoding. If not, use UTF-8
        ByteOrderMark bom = bomIn.getBOM();
        String charSet = bom == null ? defaultEncoding : bom.getCharsetName();

        //get buffered reader for speed
        InputStreamReader reader = new InputStreamReader(bomIn, charSet);
        BufferedReader breader = new BufferedReader(reader);

        //Build string to parse into XML using Processing's PApplet.parsXML
        StringBuilder buildXML = new StringBuilder();
        int c;
        while((c = breader.read()) != -1){
            buildXML.append((char) c);
        }
        reader.close();
        return p.parseXML(buildXML.toString());
    }
0 голосов
/ 11 февраля 2020

Возможно, проблема в том, что InputStream читается побайтово. Попробуйте использовать буфер, чтобы сделать его более производительным:

try (BOMInputStream bis = new BOMInputStream(new FileInputStream(new File(filename)))) {
    byte[] buffer = new byte[1000];
    while (bis.read(buffer) != -1) {
        out.write(buffer);
    }
}

Обновлено:

Результирующий ByteArrayOutputStream может содержать несколько пустых байтов в конце. Чтобы удалить их, обрежьте полученную строку:

out.toString("UTF-8").trim()
...