Fortschritt beim Schreiben einer Datei ausgeben lassen

bennsoncat

Mitglied
Hallo,
Ich habe hier eine Klasse für mein Programm erstellt, die Dateien verschlüsseln soll. Meine Idee für die nächste Version war, den Fortschritt ausgeben zu lassen. Ich habe es bereits selbst probiert, doch es wird immer nur 0 ausgegeben, außer beim letzten Durchlauf der Schleife zum Schreiben.

Wo der Fortschritt in % ausgegeben werden soll und Weiteres steht in der .java Datei als Kommentar.

Klasse:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;

public class CryptFile {

	public static KeyPair keyPair;

	static long lengthFile;

	public static boolean use3072Bit = false;

	public static KeyPair createKeyPair() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		int tmpSet;
		if (use3072Bit) {
			tmpSet = 3072;
		} else {
			tmpSet = 2048;
		}
		keyPairGenerator.initialize(tmpSet);
		return keyPairGenerator.generateKeyPair();
	}

	public static void saveKeyPair(KeyPair keyPair, String Path) throws Exception {
		File privateKey = new File(Path + File.separator + "private.bky");
		File publicKey = new File(Path + File.separator + "public.bky");

		if (new File(Path).exists()) {

			ObjectOutputStream privateOS = new ObjectOutputStream(new FileOutputStream(privateKey));
			ObjectOutputStream publicOS = new ObjectOutputStream(new FileOutputStream(publicKey));

			privateOS.writeObject(keyPair.getPrivate());
			publicOS.writeObject(keyPair.getPublic());

			privateOS.close();
			publicOS.close();

		}
	}

	public static KeyPair loadKeyPair(String Path, boolean encrypt) throws Exception {
		PublicKey publicKey = null;
		PrivateKey privateKey = null;

		if (encrypt) {
			File publicKeyFile = new File(Path + File.separator + "public.bky");
			ObjectInputStream publicIS = new ObjectInputStream(new FileInputStream(publicKeyFile));
			publicKey = (PublicKey) publicIS.readObject();
			publicIS.close();
		} else {
			File privateKeyFile = new File(Path + File.separator + "private.bky");
			ObjectInputStream privateIS = new ObjectInputStream(new FileInputStream(privateKeyFile));
			privateKey = (PrivateKey) privateIS.readObject();
			privateIS.close();
		}

		return new KeyPair(publicKey, privateKey);
	}

	private static OutputStream encryptOutputStream(OutputStream os, PublicKey publicKey) throws Exception {
		KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
		keyGenerator.init(new SecureRandom());
		Key key = keyGenerator.generateKey();

		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.WRAP_MODE, publicKey);

		byte[] wrapedKey = cipher.wrap(key);
		os.write(wrapedKey);

		cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, key);

		return new GZIPOutputStream(new CipherOutputStream(os, cipher));
	}

	private static InputStream decryptInputStream(InputStream is, PrivateKey privateKey) throws Exception {
		int tmpSet;
		if (use3072Bit) {
			tmpSet = 384;
		} else {
			tmpSet = 256;
		}
		byte[] wrappedKey = new byte[tmpSet];
		Cipher cipher = Cipher.getInstance("RSA");
		is.read(wrappedKey, 0, tmpSet);

		cipher.init(Cipher.UNWRAP_MODE, privateKey);
		Key key = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);

		cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, key);

		return new GZIPInputStream(new CipherInputStream(is, cipher));
	}

	public static void encryptFile(File sourceFile, String destionationFilePath, PublicKey publicKey) throws Exception {
		File destFile = new File(destionationFilePath);

		InputStream in = new FileInputStream(sourceFile);
		OutputStream out = encryptOutputStream(new FileOutputStream(destFile), publicKey);

		byte[] buffer = new byte[128];
		int length;

		lengthFile = 0;

		while ((length = in.read(buffer)) != -1) {
			// Hier soll der Fortschritt in % ausgegeben werden
			lengthFile += length;
			System.out.println("lF: " + lengthFile + ", sF: " + sourceFile.length()); // z.B.:
																						// >
																						// lF:
																						// 4393984,
																						// sF:
																						// 62734639
			System.out.println((lengthFile / sourceFile.length()) * 100); // Ausgabe
																			// immer
																			// 0,
																			// außer
																			// am
																			// Ende
																			// 100

			out.write(buffer, 0, length);
			//		out.flush();                  //habe ich bereits probiert
		}

		out.flush();
		out.close();
		in.close();
	}

	public static void decryptFile(File sourceFile, String destionationFilePath, PrivateKey privateKey)
			throws Exception {
		File destFile = new File(destionationFilePath);

		InputStream in = decryptInputStream(new FileInputStream(sourceFile), privateKey);
		OutputStream out = new FileOutputStream(destFile);

		byte[] buffer = new byte[128];
		int length;

		lengthFile = 0; // long

		while ((length = in.read(buffer)) != -1) {
			lengthFile += length;
			System.out.println("lF: " + lengthFile + ", sF: " + sourceFile.length()); // z.B.:
																						// >
																						// lF:
																						// 62734639,
																						// sF:
																						// 62695632
			/*
			 * Problem: lF: 62734639 größer als sF: 62695632, also über 100 %
			 * 
			 * !!!GZip soll bleiben
			 */
			System.out.println((lengthFile / sourceFile.length()) * 100); // Ausgabe
																			// immer
																			// 0,
																			// außer
																			// am
																			// Ende
																			// 100

			out.write(buffer, 0, length);
		}

		out.flush();
		out.close();
		in.close();
	}

}
 
Zuletzt bearbeitet:
Oder noch einfacher: Multipliziere erst mit 100 und teile dann ....
Danke 😉

Nun zu den anderen 2 Problemen, die ich euch hier mal mit //TODO: Problem markiert habe:

Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;

public class CryptFile {

   public static KeyPair keyPair;

   private static long lengthFile;
   private static boolean running;
   private static int prozent;

   public static boolean use3072Bit = false;

   public static KeyPair createKeyPair() throws Exception {
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
     if(use3072Bit) {
       keyPairGenerator.initialize(3072);
     } else {
       keyPairGenerator.initialize(2048);
     }
     return keyPairGenerator.generateKeyPair();
   }

   public static void saveKeyPair(KeyPair keyPair, String Path) throws Exception {
     File privateKey = new File(Path + File.separator + "private.bky");
     File publicKey = new File(Path + File.separator + "public.bky");

     if(new File(Path).exists()) {
  
       ObjectOutputStream privateOS = new ObjectOutputStream(new FileOutputStream(privateKey));
       ObjectOutputStream publicOS = new ObjectOutputStream(new FileOutputStream(publicKey));

       privateOS.writeObject(keyPair.getPrivate());
       publicOS.writeObject(keyPair.getPublic());

       privateOS.close();
       publicOS.close();
    
     }
   }

   public static KeyPair loadKeyPair(String Path) throws Exception {
     PublicKey publicKey = null;
     PrivateKey privateKey = null;
  
     if(GUIFiles.encrypt) {
       File publicKeyFile = new File(Path + File.separator + "public.bky");    
       ObjectInputStream publicIS = new ObjectInputStream(new FileInputStream(publicKeyFile));
       publicKey = (PublicKey) publicIS.readObject();
       publicIS.close();
     } else {
       File privateKeyFile = new File(Path + File.separator + "private.bky");
       ObjectInputStream privateIS = new ObjectInputStream(new FileInputStream(privateKeyFile));
       privateKey = (PrivateKey) privateIS.readObject();
       privateIS.close();
     }
  
     return new KeyPair(publicKey, privateKey);
   }

   private static OutputStream encryptOutputStream(OutputStream os, PublicKey publicKey) throws Exception {
     KeyGenerator keyGenerator =  KeyGenerator.getInstance("AES");
     keyGenerator.init(new SecureRandom());
     Key key = keyGenerator.generateKey();

     Cipher cipher = Cipher.getInstance("RSA");
     cipher.init(Cipher.WRAP_MODE, publicKey);

     byte[] wrapedKey = cipher.wrap(key);
     os.write(wrapedKey);

     cipher = Cipher.getInstance("AES");
     cipher.init(Cipher.ENCRYPT_MODE, key);

     return new GZIPOutputStream(new CipherOutputStream(os, cipher));
   }

   private static InputStream decryptInputStream(InputStream is, PrivateKey privateKey) throws Exception {
     int tmpSet;
     if(use3072Bit) {
       tmpSet = 384;
     } else {
       tmpSet = 256;
     }
     byte[] wrappedKey = new byte[tmpSet];
     Cipher cipher = Cipher.getInstance("RSA");
     is.read(wrappedKey, 0, tmpSet);

     cipher.init(Cipher.UNWRAP_MODE, privateKey);
     Key key = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);

     cipher = Cipher.getInstance("AES");
     cipher.init(Cipher.DECRYPT_MODE, key);
     
     return new GZIPInputStream(new CipherInputStream(is, cipher));
   }

   public static void encryptFile(File sourceFile, String destionationFilePath, PublicKey publicKey) throws Exception {
     File destFile = new File(destionationFilePath);

     InputStream in = new FileInputStream(sourceFile);
     OutputStream out = encryptOutputStream(new FileOutputStream(destFile), publicKey);

     byte[] buffer = new byte[128];
     int length;
  
     lengthFile = 0; //long
     running = true; //für neuen Thread (Notlösung) - nutzlos für single Cores :(
  
     new Thread(new Runnable() {
       @Override
       public void run() {
         while(running) {
           //TODO: Problem 1: Thread ausgelastet. Das verschlüsseln dauert also bei einem single core Prozessor länger
           prozent = (int) ((lengthFile * 100) / sourceFile.length());   //Berechnung wird ja oft ausgeführt - ZU OFT - Alles was ich versucht habe war unperformant, habt ihr eine gute Idee?
           System.err.println(prozent);
         }
      
       }
     }).start();
  
     while((length = in.read(buffer)) != -1)
     {
       lengthFile += length;
    
       out.write(buffer, 0, length);
     }

     running = false;
     out.flush();
     out.close();
     in.close();
   }

   public static void decryptFile(File sourceFile, String destionationFilePath, PrivateKey privateKey) throws Exception {
     File destFile = new File(destionationFilePath);
  
     InputStream in = decryptInputStream(new FileInputStream(sourceFile), privateKey);
     OutputStream out = new FileOutputStream(destFile);

     byte[] buffer = new byte[128];
     int length;
  
     lengthFile = 0; //long

     while((length = in.read(buffer)) != -1)
     {
       lengthFile += length;
       //TODO: Problem 2:
       System.out.println( (lengthFile * 100) / sourceFile.length()); //Kann über 100% ergeben
    
       out.write(buffer, 0, length);
     }

     out.flush();
     out.close();
     in.close();  
   }

}

Zum ersten:
Ich habe die Berechnung (prozent = (int) ((lengthFile * 100) / sourceFile.length()) ; )in einen neuen Thread verschoben, da das Verschlüsseln sonst länger dauert, da er es sehr oft neu berechnet. Wenn ich es aber auf einem PI mit nur einem Core ausführe, läuft es jetzt sehr langsam. Habe ihr eine Idee, wie man die Performance hier verbessern kann auch für single Cores?

Zum zweite:
Ich bräuchte die Größe der Datei am Ende... aber woher?
Oder geht das auch anders? Wenn da über 100% in der Konsole stehen, ist das auch sinnlos. Bitte Hilfe ;D
 
Zuletzt bearbeitet:
ich würde sourceFile.length() nur einmal (vor der Schleife) aufrufen und nicht in jedem Schleifendurchlauf.
Außerdem solltest du in der while-Schleife sleep aufrufen.
 
ich würde sourceFile.length() nur einmal (vor der Schleife) aufrufen und nicht in jedem Schleifendurchlauf.
Außerdem solltest du in der while-Schleife sleep aufrufen.
Gut, Problem 1 so gelöst:
Java:
  public static void encryptFile(File sourceFile, String destionationFilePath, PublicKey publicKey) throws Exception {
     File destFile = new File(destionationFilePath);

     InputStream in = new FileInputStream(sourceFile);
     OutputStream out = encryptOutputStream(new FileOutputStream(destFile), publicKey);

     byte[] buffer = new byte[128];
     int length;

     lengthFile = 0;
     running = true;
  
     new Thread(new Runnable() {
       @Override
       public void run() {
         try {
           lengthSourceFile = sourceFile.length(); //long
           while(running) {
             prozent = (int) ((lengthFile * 100) / lengthSourceFile);
             System.out.println(prozent);
             Thread.sleep(1);
           }
           System.out.println(100);
         } catch(Exception e) {}
      
       }
     }).start();
  
     while((length = in.read(buffer)) != -1)
     {
       lengthFile += length;
    
       out.write(buffer, 0, length);
     }

     running = false;
     out.flush();
     out.close();
     in.close();
   }
Nun nur noch 2. 😉
 

Neue Themen


Zurück
Oben