Program Sortujacy Zdjecia wedlug daty wykonania

0

Cześć wam, postanowiłem znów zabrać się za naukę programowania i chciałbym ukończyć program który pomoże mi posortować pliki zdjęć według daty ich wykonania. Chce aby program pobierał datę z EXIF zdjęcia, tworzył folder o nazwie "miesiąc rok" i przenosił zdjęcie do folderu. Coś tam już napisałem ale mam problem z przeniesieniem plików, i z rekurencyjną metodą "MakeListOfFiles" nie wiem czy dobrze to zaprogramowałem tak aby ListOfPhotos aktualizował się o kolejne zdjęcia w sytuacji gdy natknę się na kolejny katalog z kolejnymi zdjęciami wewnątrz katalogu głównego.
Pozdrawiam i liczę na podpowiedź

dodam tylko że błąd jaki wywala przy przenoszeniu to

java.io.FileNotFoundException: C:\Users\IM\Desktop\Zdjecia\2 2017 (Odmowa dostępu)
	at java.io.FileOutputStream.open0(Native Method)
	at java.io.FileOutputStream.open(Unknown Source)
	at java.io.FileOutputStream.<init>(Unknown Source)
	at java.io.FileOutputStream.<init>(Unknown Source)
	at apps.photoSort.App.SortFiles(App.java:60)
	at apps.photoSort.App.main(App.java:29)
package apps.photoSort;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;

public class App {

	public static void main(String[] args) {

		String sourceDirPath = "C:/Users/IM/Desktop/Zdjecia/";
		File sourceDirectory = new File(sourceDirPath);

		if (!sourceDirectory.isDirectory()) {
			System.out.println("It is not directory");
		}
		SortFiles(sourceDirectory);
	}

	private static void SortFiles(File sourceDirectory) {
		ArrayList<File> ArrayOfPhotos = MakeListOfFiles(sourceDirectory);
		Iterator<File> ArrayOfPhotosIterator = ArrayOfPhotos.iterator();
		while (ArrayOfPhotosIterator.hasNext()) {
			try {
				File nextPhoto = ArrayOfPhotosIterator.next();
				Metadata metadata = ImageMetadataReader.readMetadata(nextPhoto);
				ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
				Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
				Calendar cal = Calendar.getInstance();
				cal.setTime(date);
				int year = cal.get(Calendar.YEAR);
				int month = cal.get(Calendar.MONTH);
				StringBuilder newDir = new StringBuilder();
				newDir.append(sourceDirectory.toString());
				newDir.append("/" + month + " " + year);
				File newDirectory = new File(newDir.toString());
				System.out.println(newDirectory.toString());
				newDirectory.mkdirs();
				newDirectory.setWritable(true);

				InputStream inStream = null;
				OutputStream outStream = null;

				File oldFile = new File(nextPhoto.toString());
				File newFile = new File(newDirectory.toString());

				inStream = new FileInputStream(oldFile);
				outStream = new FileOutputStream(newFile);

				byte[] buffer = new byte[1024];

				int length;

				while ((length = inStream.read(buffer)) > 0) {

					outStream.write(buffer, 0, length);

				}

				inStream.close();
				outStream.close();

				oldFile.delete();

				System.out.println("Plik zostal przeniesiony poprawnie!");

			} catch (ImageProcessingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private static ArrayList<File> MakeListOfFiles(File sourceDirectory) {
		File[] files = sourceDirectory.listFiles();
		ArrayList<File> ListOfPhotos = new ArrayList<>();
		if (files != null) {
			for (File f : files) {
				if (!f.isDirectory()) {
					ListOfPhotos.add(f);
				} else {
					MakeListOfFiles(f);
				}
			}
		}
		return ListOfPhotos;
	}

}
0

MakeListOfFiles wygląda dobrze, choć nie wiem skąd to pytanie jak samemu możesz to sobie sprawdzić czy Ci pliki znajduje wszystkie..... :P
Ten błąd masz opisany o co chodzi: Nie może odnaleźć/otworzyć pliku do jakiego się odwołujesz w tym wypadku folderu. Zobacz czy oby na pewno masz ten folder i czy na nie jest w jakiś sposób zabezpieczony albo określony jako readonly
A po trzecie zobacz sobie FileUtils od Apache. Dzięki niemu za pomocą jednej linijki możesz zrobić to wszystko co robisz w swoim programie czyli listing plików, przekopiowanie pliku z jednego folderu do drugiego i usunięcie starego. Wygląda to mniej więcej tak

Listing:
public static Collection<File> listFiles(File directory,
                                         String[] extensions,
                                         boolean recursive)
Kopiowanie:
FileUtils.moveFileToDirectory(new File(srcFile), new File(destFile), false);
0

Program tworzy ten folder w trakcie działania. Generalnie katalog testowy wygląda tak że mam folder a w nim kilka zdjęć + kolejne 4 foldery z kolejnymi zdjęciami. Chce stworzyć listę wszystkich zdjęć włącznie z tymi w kolejnych folderach i dodać je do wspólnej listy. Potem odczytywać kolejno exify i poprzenosić je do odpowiednich świeżo utworzonych folderów.

Aktualnie moja funkcja MakeListOfFiles dodaje tylko zdjęcia z głównego folderu, nie dostaje się do pozostałych fotek lub nie dodaje ich do listy, a folder pt. 2 2017 jest utworzony przez program i nic się nie dzieje. Spróbuje z tą biblioteką do apache. Choć nie ukrywam że wolałbym napisać to przy pomocy standardowych bibliotek żeby skumać jak to działa.. Dzięki za odpowiedź

@funkcja MakeListOfFiles jest błędna, dodałem linijke System.out.println(files.length); i dostałem wynik w postaci 24 34 65 85 0 31 gdzie 0 oznacza zawartość nowo już utworzonego folderu

0

Poprawiłem funkcje MakeListOfFiles teraz działa ok,

	private static ArrayList<File> MakeListOfFiles(File sourceDirectory) {
		File[] files = sourceDirectory.listFiles();
		ArrayList<File> ListOfPhotos = new ArrayList<>();
		if (files != null) {
			for (File f : files) {
				if (f.isFile()) {
					ListOfPhotos.add(f);
				} else if (f.isDirectory()) {
					ListOfPhotos.addAll(MakeListOfFiles(f));
				}
			}
		}
		return ListOfPhotos;
	}

Dobra, udało mi się :D Działa spoko teraz moge posortować moje zdjęcia około 1TB :D

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

import org.apache.commons.io.FileUtils;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;

public class App {

	public static void main(String[] args) {
		String sourceDirPath = "C:/Users/IM/Desktop/Gabo kucharz/";
		File sourceDirectory = new File(sourceDirPath);

		if (!sourceDirectory.isDirectory()) {
			System.out.println("It is not directory");
		}
		SortFiles(sourceDirectory);
	}

	private static void SortFiles(File sourceDirectory) {
		ArrayList<File> ArrayOfPhotos = MakeListOfFiles(sourceDirectory);
		System.out.println(ArrayOfPhotos.size());
		Iterator<File> ArrayOfPhotosIterator = ArrayOfPhotos.iterator();

		while (ArrayOfPhotosIterator.hasNext()) {
			try {
				File nextPhoto = ArrayOfPhotosIterator.next();
				Metadata metadata = ImageMetadataReader.readMetadata(nextPhoto);
				ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
				Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
				Calendar cal = Calendar.getInstance();
				cal.setTime(date);
				int year = cal.get(Calendar.YEAR);
				int month = cal.get(Calendar.MONTH);
				StringBuilder newDir = new StringBuilder();
				newDir.append(sourceDirectory.toString());
				newDir.append("/" + month + " " + year);
				FileUtils.moveFileToDirectory(nextPhoto, new File(newDir.toString()), true);

			

			} catch (ImageProcessingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				
			}
			
		}
	}

	private static ArrayList<File> MakeListOfFiles(File sourceDirectory) {
		File[] files = sourceDirectory.listFiles();
		ArrayList<File> ListOfPhotos = new ArrayList<>();
		if (files != null) {
			for (File f : files) {
				if (f.isFile()) {
					ListOfPhotos.add(f);
				} else if (f.isDirectory()) {
					ListOfPhotos.addAll(MakeListOfFiles(f));
				}
			}
		}
		return ListOfPhotos;
	}
}
0

Pytanie za 100 punktów, jakis sposob zeby przyspieszyc dzialanie tego? Masakra jak dlugo dziala,

0

Hmm, najlogiczniejsze będzie stworzenie wątków, żeby np. każdy zajmował się swoim folderem itd. Innego sposobu na przyśpieszenie nie widzę/znam. Możesz też najpierw pomierzyć czasy co dokładnie najwięcej czasu Ci zajmuje ale na 99% będzie to właśnie przenoszenie plików. Czasy pomierz sobie za pomocą np.

long startTime = System.currentTimeMillis();
long estimatedTime = System.currentTimeMillis() - startTime;
System.out.println(estimatedTime);
	

albo bardzo precyzyjnie za pomocą :

System.nanoTime();  

ale aż takiej precyzji raczej nie potrzebujesz.
A i jeszcze jedno, nie wykonuj w while bez przerwy Calendar cal = Calendar.getInstance(); bo nie widzę sensu. Pobierz instancję raz przed while i tyle. Powinno działać.

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