Projekt do jara - nie działa (prawdopodobnie błąd z zasobami)

0

Jakiś czas temu zmieniałem telefon i przez przypadek skasowałem wszystkie kontakty. Miałem na szczęście backup smsów w formie xmla, więc mogłem niektóre kontakty odzyskać. To też na szybko naklepałem program (więc nie, nie jest to czysty kod, ale w tym przypadku to naprawdę raczej nieistotne). Ogólnie program działa i spełnił swoje zadanie. Postanowiłem zobaczyć jak działa jako plik jar. Niestety od kilku godzin się męczę na różne sposoby, szukam rozwiązania w książkach i na necie i nic (mam nadzieję, że po porostu źle szukałem i odpowiedź jest gdzieś na wyciągnięcie ręki).

Magia dzieje się, a raczej NIC się nie dzieje (a przynajmniej tak mi się zdaje) w metodzie zrobTo(), a dokładniej w linijce 44, 45:

InputStream input = this.getClass().getResourceAsStream("../resources/smsy.xml");
		Document document = builder.parse(input);

Najpierw używałem File'a, ale potem doczytałem i przypomniałem sobie, że zasoby w jarze możemy tylko wyciągać przez metodę getClass().getResourceAsStream(...) (chyba, że się mylę).

Ogólnie rzecz biorąc:

  1. Jak odpalę program po prostu w eclipse, to wszystko działa, a na pulpicie tworzą mi się 2 pliki txt - dobrze wypełniony plik kontakty.txt oraz log.txt, który zawiera 4x napis "test".
  2. Jak wyślę do jara (zgodnie z tym tutorialem: ), to na pulpicie tworzy mi się tylko PUSTY plik log.txt, co dla mnie jest dość dziwne.

Co zrobić, żeby to działało po wysłaniu do jara? Jakoś inaczej zasoby dodawać?

Kod: (klasa Contact to zwyczajna klasa z 3 polami i getterami do nich, tyle)

package Num;

import java.io.*;
import java.util.*;

import javax.xml.parsers.*;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

public class Numery
{
	private FileWriter log;
	public static void main(String[] args) throws IOException
	{
		File file = new File(System.getProperty("user.home"), "Desktop/log.txt");
		Numery numery = new Numery();
		numery.log = new FileWriter(file);
		try
		{
			numery.log.append("test\n");
			numery.zrobTo();
		} 
		catch (IOException | SAXException | ParserConfigurationException e)
		{
			numery.log.append(e.toString() + "\n");
		}
		
		numery.log.close();
	}
	
	public void zrobTo() throws IOException, SAXException, ParserConfigurationException
	{	
		log.append("test\n");
		TreeSet<Contact> uniqueContacts = new TreeSet<>();
		String name;
		String number;
		String date;

		log.append("test\n");
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		log.append("test\n");
		InputStream input = this.getClass().getResourceAsStream("../resources/smsy.xml");
		Document document = builder.parse(input);
		
		Element root = document.getDocumentElement();
		NodeList chilrder = root.getChildNodes();
		
		for(int i = 0; i < chilrder.getLength(); ++i)
		{
			Node child = chilrder.item(i);
			if(child instanceof Element)
			{
				Element childElement = (Element) child;
				number = childElement.getAttribute("address");
				if(number.startsWith("+48"))
					number = number.substring(3);
				name = childElement.getAttribute("contact_name");
				date = childElement.getAttribute("readable_date");
				if(!"(Unknown)".equals(name))
					uniqueContacts.add(new Contact(number, name, date));
			}
		}
		
		
		List<Contact> contacts = new ArrayList<>();
		contacts.addAll(uniqueContacts);
		
		contacts.sort(Comparator.comparing(Contact::getName).thenComparing(Contact::getDate));
		

		File file2 = new File(System.getProperty("user.home"), "Desktop/kontakty.txt");
		FileWriter writer = new FileWriter(file2);
		
		for(Contact contact : contacts)
			writer.append(contact.toString());
			
		writer.close();
	}

}

Drzewko folderów w załączniku

EDIT:
po dopisaniu na końcu wywołania catch w metodzie main numery.log.close() - nic się nie zmieniło
tak wygląda plik meta-inf:
Manifest-Version: 1.0 Class-Path: . Main-Class: Num.Numery

1

Masz błędną ścieżkę w metodzie getResourceAsStream. Twoja ścieżka opisuje jak dojść od pliku Numery.java do pliku XML, a powinna opisywać jak dojść od pliku Numery.class do pliku XML.

0

Nie wiem czy w ten sposób uzyskam ścieżkę o której mówiłeś, ale spróbowałem tak:

InputStream input = Numery.class.getResourceAsStream("../resources/smsy.xml");

Wynik niestety ciągle taki sam.

0

Przecież nie zmieniłeś ścieżki, jest dokładnie taka sama jak była. Jeżeli chcesz mieć taką ścieżkę, to przenieś plik XML. Ten plik ma bardzo dziwną lokalizację - jest w folderze src, który w pliku jar jest całkowicie zbędny.
Jar, to zip z innym rozszerzeniem. Przemianuj (zrób kopie) i zobacz czy plik XML jest w jarze, a jeśli jest, to jaka jest ścieżka względna od pliku Numery.class do pliku XML.

0

Jak tworzę plik resources w folderze src to automatycznie mi się taki tworzy w folderze bin. Koniec końców w archiwum jar mam 3 foldery:
META-INF:
~ MANIFEST.MF
Num:
~ Numery.class
~ Contact.class
resources:
~ smsy.xml

Więc od klasy Num wychodzę "wyżej" (../) by potem wejść do resources/smsy.xml. Nie wiem czemu nie działa.
Zastanawia mnie też, czemu plik log.txt wychodzi pusty, nie wypisując nawet pierwszego 'test'.


EDIT:

Ok. Wreszcie znalazłem rozwiązanie swojego problemu:

Zastanawia mnie jednak dlaczego jar nie akceptuje tego: ../ w ścieżce. Co ciekawe o ile normalnie w eclipsie taki skok jest możliwy, to wyjście o dwa poziomy w górę (../../) też wywala NullPointerException.

1 użytkowników online, w tym zalogowanych: 0, gości: 1