# Zugriff Verweigert bei Kopieroperation?



## florilu (12. Jan 2013)

Hallo ihr,

ich habe ein kleines Problem, ich habe für meine Mod jetzt einen Installer geschrieben, da mich mehrere drum gebeten haben, alles funktioniert einwandfrei, nur wenn ich versuche die Datei in einen Ordner zu kopieren kriege ich folgende Meldung:


```
java.io.FileNotFoundException: C:\Users\Florian\AppData\Roaming\.minecraft\EBGBackup (Zugriff verweigert)
at java.io.FileOutputStream.open(Native Method)
	at java.io.FileOutputStream.<init>(Unknown Source)
	at java.io.FileOutputStream.<init>(Unknown Source)
	at CopyFile.copy(CopyFile.java:29)
	at Main.main(Main.java:47)
```

Bei folgendem Code:
Main.java

```
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class Main
{
	static String path = System.getProperty("user.home") + File.separatorChar + "AppData/";
	static String mainFolder = System.getProperty("user.home") + File.separatorChar + "Appdata/Roaming/.minecraft/";
	static String test = System.getProperty("user.home");
	
	static File backup = new File(path + "Roaming/.minecraft/EBGBackup/");

	static File minecraft = new File(path + "Roaming/.minecraft/bin/minecraft.jar");
	static File mcOut = new File(path + "Roaming/.minecraft/EBGBackup/");
	static File finalOut = new File(path + "Roaming/.minecraft/bin/minecraft.jar");

	static Scanner scanner = new Scanner(System.in);
	
	static File readme;
	static FileWriter writer;

	public static void main(String[] args) throws Exception {
		
		System.out.println("EBG Installation Assistant for EBG V1.2.4 (1.4.7) by Florilu");
		System.out.println("Options: ");
		System.out.println("Install:     [1]");
		System.out.println("Refresh jar: [2]");
		System.out.println("Exit:        [3]");
		System.out.print("Choose Optionnumber: ");
		int num = scanner.nextInt();
		if (num == 1) {
			if(!backup.exists()){
				backup.mkdir();
			}
			
			if(backup.exists()){
				System.out.println(minecraft + " " + mcOut);
				System.out.println("Backupping your jar!");
				check();
				CopyFile.copy(minecraft, mcOut);
				check();
				System.out.println("Backup Complete!");
			}
			new Main().extractArchive(new File("files/install.zip"), new File(path + "Roaming/.minecraft/bin"));
			System.out.println("ExtraBiomesGen has been installed.");
		}
		if (num == 3) {
			System.exit(0);
		}
		if (num == 2){
			if (!minecraft.exists()) {
				new Main().extractArchive(new File("files/refresh.zip"), new File(path + "Roaming/.minecraft/bin"));
				System.out.println("Your jar has been refreshed!");
			}else{
				minecraft.delete();
				new Main().extractArchive(new File("files/refresh.zip"), new File(path + "Roaming/.minecraft/bin"));
				System.out.println("Your jar has been refreshed!");
			}
		}
	}
	
	public static void check(){
		System.out.println("CanRead:" + mcOut.canRead());
		System.out.println("CanWrite" + mcOut.canWrite());
		System.out.println("Exists:" + mcOut.exists());
		System.out.println("AbsolutePath:" + mcOut.getAbsolutePath());
		System.out.println("IsDirectory:" + mcOut.isDirectory());
	}
	
	public static void write() throws IOException{
		String text = "The Backupfunction is still WIP, be sure you'll backup your jar by yourself!";
		String dateiName = mainFolder + "EBGBackup/README.txt";
		FileOutputStream schreibeStrom = new FileOutputStream(dateiName);
		for (int i=0; i < text.length(); i++){
			schreibeStrom.write((byte)text.charAt(i));
		}
		schreibeStrom.close();
	}
	
	public void extractArchive(File archive, File destDir) throws Exception {
		if (!destDir.exists()) {
			destDir.mkdir();
		}
		
		minecraft.delete();
		
		write();

		ZipFile zipFile = new ZipFile(archive);
		Enumeration entries = zipFile.entries();

		byte[] buffer = new byte[16384];
		int len;
		while (entries.hasMoreElements()) {
			ZipEntry entry = (ZipEntry) entries.nextElement();

			String entryFileName = entry.getName();

			if (entry.isDirectory()) {
				File dir = new File(destDir, entryFileName);
				// System.out.println(dir);
				if (!dir.exists()) {
					dir.mkdir();
				}
			} else {

				BufferedOutputStream bos = new BufferedOutputStream(
						new FileOutputStream(new File(destDir, entryFileName)));

				BufferedInputStream bis = new BufferedInputStream(zipFile
						.getInputStream(entry));

				while ((len = bis.read(buffer)) > 0) {
					bos.write(buffer, 0, len);
				}

				bos.flush();
				bos.close();
				bis.close();
			}
		}
	}
}
```

CopyFile.java

```
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.ByteChannel;
import java.nio.channels.FileChannel;
public class CopyFile {
	static long chunckSizeInBytes;
	boolean verbose;
	public CopyFile(){
		this.chunckSizeInBytes = 1024 * 1024; //Standard: Buffer 1MB
		this.verbose = false; //Statistics about Copy Process
	}
	public CopyFile(boolean verbose){
		this.chunckSizeInBytes = 1024 * 1024; //Standard: Buffer 1MB
		this.verbose = verbose; //Statistics about Copy Process
	}
	public CopyFile(long chunckSizeInBytes){
		this.chunckSizeInBytes = chunckSizeInBytes; //Custom Buffer (Bytes)
		this.verbose = false; //Statistics about Copy Process
	}
	public CopyFile(long chunckSizeInBytes, boolean verbose){
		this.chunckSizeInBytes = chunckSizeInBytes; //Custom Buffer (Bytes)
		this.verbose = verbose; //Statistics about Copy Process
	}
	public static void copy(File source, File destination) {
		try {
			FileInputStream fileInputStream = new FileInputStream(source);
			FileOutputStream fileOutputStream = new FileOutputStream(destination);
			FileChannel inputChannel = fileInputStream.getChannel();
			FileChannel outputChannel = fileOutputStream.getChannel();
			transfer(inputChannel, outputChannel, source.length(), false);
			fileInputStream.close();
			fileOutputStream.close();
			destination.setLastModified(source.lastModified());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void transfer(FileChannel fileChannel, ByteChannel byteChannel, long lengthInBytes, boolean verbose)
			throws IOException {
		long overallBytesTransfered = 0L;
		long time = -System.currentTimeMillis();
		while (overallBytesTransfered < lengthInBytes) {
			long bytesTransfered = 0L;
			bytesTransfered = fileChannel.transferTo(overallBytesTransfered, Math.min(chunckSizeInBytes, lengthInBytes - overallBytesTransfered), byteChannel);
			overallBytesTransfered += bytesTransfered;
			if (verbose) {
				System.out.println("overall bytes transfered: " + overallBytesTransfered + " progress " + (Math.round(overallBytesTransfered / ((double) lengthInBytes) * 100.0)) + "%");
			}
		}
		time += System.currentTimeMillis();
		if (verbose) {
			System.out.println("Transfered: " + overallBytesTransfered + " bytes in: " + (time / 1000) + " s -> " + (overallBytesTransfered / 1024.0) / (time / 1000.0) + " kbytes/s");
		}
	}
}
```

Und mein Debugmode sagt:

```
CanRead:true
CanWritetrue
Exists:true
AbsolutePath:C:\Users\Florian\AppData\Roaming\.minecraft\EBGBackup
IsDirectory:true
```

Alles bezieht sich auf:

```
static File mcOut = new File(path + "Roaming/.minecraft/EBGBackup/");
```
In diesen Ordner soll die minecraft.jar reinkopiert werden.

Wie kann ich das Problem lösen? Ich habe mich schon stundenlang durchgegooglet aber nichts gefunden 

MfG:
Florilu


----------



## bERt0r (12. Jan 2013)

Das Problem ist wohl, dass du Administratorrechte brauchst um in dem Ordner herumzuändern. Request admin privileges for Java app on Windows Vista - Stack Overflow


----------



## florilu (12. Jan 2013)

Das Witzige an der Sache ist, ich kann einfach ohne Probleme irgendwelche Dateien drin erstellen oder löschen oder mehrere Unterordner anlegen, aber beim Kopieren der minecraft.jar will es nicht...
Ist da vllt was an dem Pfad falsch? Ich habe momentan eher das Gefühl, da der Ordner in der Laufzeitumgebung geöffnet ist, und das dass Programm versucht den Ordner zur .jar zu ändern? Denn dann kriegt man auch so wenn man das selbst macht Probleme. Und mit Adminrechten habe ich es auch versucht, hat leider auch nicht geklappt.


----------



## tröööt (13. Jan 2013)

bERt0r hat gesagt.:


> Das Problem ist wohl, dass du Administratorrechte brauchst um in dem Ordner herumzuändern. Request admin privileges for Java app on Windows Vista - Stack Overflow



du hast aber schon im code gelesen das hier USER.HOME genutzt wird ... oder ? und auch unter windows hat man genau wie unter unix in USER.HOME und allen unter-ordnern VOLLZUGRIFF ... sogar noch mehr als bei unix ... denn wenn man unter unix als root in nem home-dir was erstellt hat auch nur root access .. unter win hat ein user selbst dann access wenn etwas vom admin gemacht wurde ...

DAS scheidet also als fehlerquelle definitiv aus ..


@TO

naja ... lesen sollte man können ...

[java=20]static File minecraft = new File(path + "Roaming/.minecraft/bin/minecraft.jar");[/code]
verweist ganz klar auf eine DATEI
[java=21]static File mcOut = new File(path + "Roaming/.minecraft/EBGBackup/");[/code]
makiert jedoch klar ein VERZEICHNIS
[java=28]FileInputStream fileInputStream = new FileInputStream(source);
FileOutputStream fileOutputStream = new FileOutputStream(destination);[/code]
ergibt dann also mal mit eingesetzten parametern
[java=28]FileInputStream fileInputStream = new FileInputStream(new File(path + "Roaming/.minecraft/bin/minecraft.jar"));
FileOutputStream fileOutputStream = new FileOutputStream(new File(path + "Roaming/.minecraft/EBGBackup/"));[/code]

so wird der fehler offensichtlich : du versuchst das VERZEICHNIS "Roaming/.minecraft/EBGBackup/" als DATEI mit einem DATEI-OUTPUT-STREAM zu öffnen ... und DAS GEHT NICHT !

"ZUGRIFF VERWEIGERT" kommt vermutlich daher weil java versucht ein verzeichnis-handle als output-file zu öffnen ... was schlicht nicht unterstützt wird ... aber für genau infos müsste man mal in den source der native-method und ins MSDN gucken ...

die lösung ist also das du
entweder zeile 21 so änderst das mcOut auf eine DATEI zeigt ... NICHT auf ein VERZEICHNIS
oder du copy() so abwandelst das es auch als VERZEICHNIS entgegen genommen wird und du darauf mit "new File(File, String)" einen neuen handle auf eine dann zu erstellen DATEI angibst ...

und btw : zeile 20 und 22 zeigen auf das selbe objekt ... warum also zwei mal damit speicher verschwenden ? tipp-fehler ? oder ist das so gewollt ... wenn ja : eins von beien kannst du löschen
genau wie 18 und 21 .. zeigen auch beide aufs selbe ...


----------



## florilu (14. Jan 2013)

Also lag ich mit meiner Theorie net falsch


----------

