Optymalizacja funkcji pakujacej plik

0

Siemka. Jestem w trakcie tworzenia czegos na wzor torrenta.
Napisalem funkcje ktora dzieli plik na 3 byte[] i przesyla klientowi. Klient go sklada i jak dla malutkich plików(66 bajtow) sklada szybciutko Niestety wieksze pliki(69mb) sklada w... nie powiem bo nie wiem po 10 min wylaczylem :P
Moja funkcja skladajaca wyglada tak:
Czy ktos móglby mi pomóc zoptymalizowac to zadanie?

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.io.FileOutputStream;

public class skladacz {

	public static void main(String[] args) throws IOException {
		File newFile1 = new File("C:\\arty\\part"+0);
		File newFile2 = new File("C:\\arty\\part"+1);
		File newFile3 = new File("C:\\arty\\part"+2);
		
		byte[] a = Files.readAllBytes(newFile1.toPath());
		byte[] b = Files.readAllBytes(newFile2.toPath());
		byte[] c = Files.readAllBytes(newFile3.toPath());
		
		
		File newFile = new File("C:\\arty\\test.pdf");
		FileOutputStream fos = new FileOutputStream(newFile.toPath().toString());
		byte[] d = new byte[a.length+b.length+c.length];
		int j=0;
		
		System.out.println("zaczynam pakowac");
		for(int i=0; i<newFile1.length();i++){
			d[j] = a[i];
			j++;
		}
		System.out.println("zlozono 1");
		for(int i=0; i<newFile2.length();i++){
			d[j] = b[i];
			j++;
		}
		System.out.println("zlozono 2");
		for(int i=0; i<newFile3.length();i++){
			d[j] = c[i];
			j++;
		}
		System.out.println("zlozono 3");
		
			fos.write(d);
			System.out.println("skonczone");
	}
	

}

Oczywiscie jest to funkcja testowa automatyzacja zajme sie po tym. Juz na oko widze ze ten kod ma powazny problem musi przeleciec przez kilka ok 72 milliony bajtow(niefajnie:( )

1

Pierwsza rzecz, która mi się rzuciła w oczy to to że w pętli przy każdej iteracji odczytujesz długość pliku, co jest prawdopodobnie bardzo nieefektywne, gdyż jeśli nie jest to jakoś cache'owane to ta funkcja za każdym razem odczytuje te dane z dysku. Spróbuj to zastąpić przez odwołanie do długości konkretnej tablicy, np. i < a.length.

1

A może użyjesz choćby https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html zamiast przepisywać te bajty jeden po drugim? o_O

1

adwy 69mb przegrało:D Teraz cos wiekszego jeszcze wrzuce i zaimplementuje ByteArrayOutputStream.
Super jestescie az czlowiek chce sie uczyc:D

1

Można sobie ułatwić życie pisząc za pomocą strumieni albo kanałów. Kanały (Channel) umożliwiają pracę z danymi pociętymi na bufory o określonej długości:

RandomAccessFile aFile     = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel      inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(aFile.length());
int bytesRead = inChannel.read(buf);

// i późnej 

buf.flip();

while(buf.hasRemaining()) {
    channel.write(buf);
}

W połączeniu z np. strumieniem plików:

Arrays.stream(folder.listFiles()) // wszystkie pliki w folderze tymczasowym
    .filter(nameFIlter) // tylko pliki, które są częścią naszej komunikacji
    .reduce(joiner); // złożenie plików w całość jak wyżej

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