Java: Как сохранить Vector <String []> в XML (или сохранить любым другим способом) - PullRequest
1 голос
/ 27 апреля 2010

По сути, у меня есть приложение для проверки концепции, которое представляет собой цифровую книгу рецептов. Каждый Рецепт является объектом, и каждый объект, помимо других полей, имеет Вектор, содержащий массивы. Вектор - это список всех ингредиентов в рецепте, в то время как каждый ингредиент имеет массив, показывающий название ингредиента, количество и единицу измерения для этого количества. Я хочу сохранить каждый рецепт в XML, чтобы пользователь мог получить к ним доступ. Как я могу сохранить массивы Vector of String в XML или любом другом виде файла, чтобы впоследствии к нему можно было обращаться и получать к нему доступ?

Ответы [ 3 ]

2 голосов
/ 27 апреля 2010

Почему бы не смоделировать ингредиент как реальный объект? Затем у вас есть последовательность ингредиентов в разделе «Рецепт», каждый со своими подэлементами или атрибутами имени, количества, единицы и т. Д.

1 голос
/ 27 апреля 2010

Существует несколько методов генерации XML, каждый из которых имеет свои преимущества и недостатки. Самым простым для реализации (но самым трудным сделать правильно) является сборка XML вручную.

Если вы хотите, чтобы список ингредиентов выглядел примерно так:

<ingredients>
  <ingredient name="ginger"/>
  <ingredient name="cinnamon"/>
  <ingredient name="sugar"/>
</ingredients>

Вам нужен код для обхода вектора:

System.out.println("<ingredients>");
Vector ingredients;
for (String name : ingredients) {
  System.out.print("  <ingredient name=\"");
  System.out.print(name);
  System.out.println("\"/>");
}
System.out.println("</ingredients>");

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

Гораздо лучше использовать библиотеку XML для генерации XML. Хорошая библиотека XML всегда будет генерировать действительный XML.

import java.io.FileWriter;
import com.megginson.sax.XMLWriter;
import org.xml.sax.helpers.AttributesImpl;

public class GenerateXML
{

    public static void main (String args[])
    throws Exception
    {
    XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));

    writer.startDocument();
    writer.startElement("","ingredients","",null);
    for (String ingredient : ingredients) {
        AttributesImpl attribs = new AttributesImpl();
        attribs.addAttribute("","name","","",ingredient);
        writer.startElement("", "ingredient","",attribs);
        writer.endElement("ingredient");
    }
    writer.endElement("ingredients");
    writer.endDocument();
}

Для более полного описания того, что возможно с DOM XMLWriter, смотрите http://docstore.mik.ua/orelly/xml/sax2/ch02_02.htm с особым вниманием к разделу 2.2.3.

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

Кроме того, хотя вы можете начать с чего-то вроде массивов Vector of String, такая структура данных имеет мало общего с реальными представлениями о том, что влечет за собой рецепт. Возможно, в конечном итоге вам лучше будет использовать класс Recipie, который содержит классы для ингредиентов и инструкции (которые, в свою очередь, содержат шаги). Хотя может показаться, что для трех или четырех различных типов классов может потребоваться больше усилий, эта предварительная работа экономит более чем в десять раз эквивалентный объем работы при выполнении последних 10% выполненной программы.

Даже для «быстрого» подтверждения концепции экономия времени при использовании действительно описательной структуры данных может быть значительной; поскольку доказательство концепции может быстро стать начальным прототипом, который затем может стать основой для реального выпуска.

Удачи и счастливого программирования!

0 голосов
/ 27 апреля 2010

Чтобы быстро оторваться от земли, вы можете использовать XStream . По умолчанию он производит хороший вывод и очень гибок, так что вы можете получить почти все, что хотите в XML.

Вы можете сериализовать объект в XML, написав

String xml = XStream.toXML(myObject);

Что касается структуры, вы можете продолжать использовать векторы и списки, когда заранее не знаете их количество, но лучше использовать список объектов домена (рецепты, ингредиенты и т. Д.), А не массивы строк. С XStream вам не нужно делать все строки, чтобы получить их в XML.

Если вы действительно хотите оставить все как есть без изменений, то поведение XStream по умолчанию может не дать вам того, что вы хотите. Он не знает, какие строки являются рецептами, ингредиентами и т. Д. В этом случае вам придется написать немного больше. Например, этот код записывает вектор, как рецепты с ингредиентами, в файл "recipes.txt":

Vector<String[]> recipes = ... (your vector of recipes)
PrettyPrintWriter writer = new PrettyPrintWriter(new FileWriter("recipes.txt"));
writer.startNode("recipes");
for (String[] recipe: recipes)
{
   writer.startNode("recipe");
   // you might write out attributes, such as the recipe name
   for (String ingredient: recipe)
   {
      writer.startNode("ingredient");
      writer.setValue(ingredient);
      writer.endNode();
   }
   writer.endNode();
}
writer.endNode();
writer.close();

Для вектора

Vector<String[]> v = new Vector<String[]>();
v.add("2 cups pasta", "1 onion");
v.add("2 eggs", "1.5 cups sugar", "1 tbsp butter");

вывод будет

<recipes>
   <recipe>
      <ingredient>2 cups pasta</ingredient>
      <ingredient>1 onion</ingredient>
   </recipe>
   <recipe>
      <ingredient>2 eggs</ingredient>
      <ingredient>1.5 cups sugar</ingredient>
      <ingredient>1 tbsp butter</ingredient>
   </recipe>
</recipes>
...