Запись Stax XML в ObjectOutputStream (socket.getOutputStream) получение исключения MalformedByteSequenceException

#java #xml #sockets #unicode #stax

#java #xml #сокетов #unicode #stax

Вопрос:

Я пытаюсь отправить XML-сообщение на сервер из клиентского приложения, используя сокеты на Java, но я не знаю, как записать его в поток:

         String user = "Oscar"
        String pass = "1234"

        ObjectOutputStream oos = new ObjectOutputStream(
                socket.getOutputStream());

        // Create a XMLOutputFactory
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();

        // Create XMLEventWriter
        XMLEventWriter eventWriter = outputFactory
                        .createXMLEventWriter(oos);

        // Create a EventFactory
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();

        XMLEvent end = eventFactory.createDTD("n");

        // Create and write Start Tag
        eventWriter.add(eventFactory.createStartDocument());
        eventWriter.add(end);

        //Se crean los atributos del tag
        ArrayList<Attribute> attributes = new ArrayList<Attribute>();
        attributes.add(eventFactory.createAttribute("nickname", user));
        attributes.add(eventFactory.createAttribute("password", pass));

        eventWriter.add(eventFactory.createStartElement
            ("", "", "authenticate",attributes.iterator(), null));
        eventWriter.add(end);

        eventWriter.add(eventFactory.createEndElement("", "", "authenticate"));

        eventWriter.add(eventFactory.createEndDocument());
  

должен ли я использовать:

         eventWriter.flush();
  

?

если я это сделаю, это даст мне следующее исключение:

javax.xml.stream.XMLStreamException: исключение com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: недопустимый байт 1 из 1-байтовой последовательности UTF-8.

Он говорит, что я неправильно пишу сообщение. Тогда, каков способ записи?

Сообщение должно быть:

 <?xml version="1.0" encoding="UTF-8"?>"  
<authenticate nickname="Oscar" password="1234" />
  

И вот код, который я использую на сервере для чтения сообщения:

 //the call
this.Interpreter.readCommand(socket.getInputStream());
  

и

 //the method
@SuppressWarnings({ "unchecked", "null" })
public void readCommand(InputStream command) {

    try {

        // Fabrica de entrada de XML
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();

        // Se crea un nuevo eventReader
        XMLEventReader eventReader = inputFactory.createXMLEventReader(command);

        while (eventReader.hasNext()) {

            XMLEvent event = eventReader.nextEvent();

            if (event.isStartElement()) {

                StartElement startElement = event.asStartElement();

                // Si tenemos un comando authenticate
                if (startElement.getName().getLocalPart().equals("authenticate")) {

                    CommandAuthenticate(startElement);
                }

            }

        }

    }
    catch (XMLStreamException e) {
        e.printStackTrace();
    }
}


public void CommandAuthenticate (StartElement startElement){


    String nickname = null;
    String password = null;

    // Se leen los atributos del comando
    Iterator<Attribute> attributes = startElement
                    .getAttributes();

    while (attributes.hasNext()) {

        Attribute attribute = attributes.next();

        if (attribute.getName().toString().equals("nickname")) {

            nickname = attribute.getValue();
        }

        if (attribute.getName().toString().equals("password")) {

            password = attribute.getValue();
        }

    }

    //here i call the right method for the data received

}
  

Ответ №1:

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

в качестве дополнительного примечания / общего правила, ваши настройки inputstream и outputstream обычно должны совпадать. если вам по какой-либо причине действительно понадобилось использовать и ObjectOutputStream, вам понадобится ObjectInputStream на другом конце, чтобы соответствовать ему.

Комментарии:

1. Вы тоже были правы, но Том Андерсон ответил первым. В любом случае спасибо за вашу помощь

2. На самом деле, я думаю, что jtahlborn опередил меня на несколько секунд. Оскар, некоторые люди предполагают, что если вы получите несколько одинаково хороших ответов, вы должны принять один, но затем проголосовать за остальные. Это способ придать всем ответам некоторую узнаваемость.

3. да, я думаю, что я был первым, но жизнь продолжается. 🙂

Ответ №2:

Не используйте ObjectOutputStream. Это для сериализации. Вы не выполняете сериализацию. Просто попросите XMLEventWriter записать непосредственно в поток сокета. Аналогично, у вас нет ObjectInputStream на стороне чтения.

Причина сбоя в том, что ObjectOutputStream добавляет заголовок к потоку, который блокируется анализатором XML.

Комментарии:

1. Спасибо, я очень ценю вашу помощь.