FileChannel (inChannel/outChanel) Fehler wenn Leerzeichen enthalten

  • Themenstarter Gelöschtes Mitglied 56712
  • Beginndatum
G

Gelöschtes Mitglied 56712

Gast
Guten Tag

wenn:
Java:
inChannel = new FileInputStream(file).getChannel();

file Leerzeichen enthält, wird mir der Zugriff verweigert.
Erstelle ich ein File renamIn = new File(file.getPath().replaceAll(" ", "§"));
und dieses dann dem inChanel resp. outChanel übergebe, wird es nicht gefunden!

Weiss jemand wie man das am einfachsten lösen kann?

Mein Ansatz:
Code:
    File inputF = file;
    String aktInFile = inputF.getAbsolutePath().replaceAll(" ", "§");
    File renamIn = new File(aktInFile);
                       
    //file am Ursprung umbenennen und dem inChannel übergeben.
    inputF.renameTo(renamIn);
    File forCPin = renamIn;
    inChannel = new FileInputStream(forCPin).getChannel();
                       
    inChannel.transferTo(0, inChannel.size(), outChannel);
                       
    //Umbenennen rückgängig machen (in original file)
    forCPin.renameTo(f);
Dies funktioniert soweit... (Wenn der Anwender Schreibzugriff hat)
Aber bei 3000 Dateien extrem langsam, zumal dies auch für die Gegenseite von transferTo(...) gemacht werden muss.
(sofern der Zielort nicht Lokal ist)

Für Tips bin ich sehr Dankbar.
 
Zuletzt bearbeitet von einem Moderator:
G

Gelöschtes Mitglied 56712

Gast
Fehlermeldung bei nicht behandeltem File:
Java:
java.io.FileNotFoundException: /media/benutzername/ftp/domain.ch/Bilder/Test Kopie.png (Keine Berechtigung)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
    at basics.WindowSettings.copyFile(WindowSettings.java:179)
    at bigCopy.BigCopy.sizeChecker(BigCopy.java:393)
    at bigCopy.BigCopy.main(BigCopy.java:109)
 
G

Gelöschtes Mitglied 56712

Gast
Habe es jetzt so gelösst:
Prüfe erst:
Java:
System.getProperty("os.name");
und verwende entsprechende Konsolenbefehle.
Da wird kein File() übergeben sonden ein String welchen ich mit Hochkommas versehe.
Beispiel Linux: (auch mac und andere UNIX-Systemen)
cp '/media/benutzername/ftp/domain.ch/Bilder/Test Kopie.png' '.../Bilder/Test Kopie.png'
Auch in Windows kann man so (mit den dos-Befehlen) arbeiten.

Vielen Dank.
 

Robert Zenz

Top Contributor
Das hat aber nichts mit dem FileChannel zu tun wenn ich das richtig sehe, du kannst auch mit dem FileInputStream nicht auf die Datei zugreifen weil du eben keine Berechtigung hast. Wieso das so sein sollte ist etwas schwerer zu sagen, entweder das Dateisystem welches da eingehaengt ist macht komische Sachen, oder SELinux verbietet es. Ersteres klingt nach einem interessanten Kandidaten wenn das ueber FTP geht. Wobei da vielleicht ein "richtiger" FTP-Client besser waere, vielleicht, kommt darauf an was du machst.

In der neuen Java NIO API gibt es die Files Klasse welche eine copy(Path, Path) Methode hat. Vielleicht reicht dir das ja aus anstatt da mit den FileChannel zu handieren (was mir ohnehin eigenartig vorkommt).

Wieso gehst du eigentlich auf FileChannel-Ebene hinunter? Der obige Code kann mit Streams genauso gemacht werden, oder sogar mit `Path`s.
 
G

Gelöschtes Mitglied 56712

Gast
Wobei da vielleicht ein "richtiger" FTP-Client besser waere
Das Laufwerk wird als "richtiges" FTP eingehängt!
curlftpfs#ftp://ftp.domain.xxx/ (mit allen relevanten Benutzerinformationen und entsprechenden Rechten)
(verwende ein Linux-System)

Das "ftp" im Pfadname ist nur mein Ordner in dem obiges eingehängt wird!
anstatt da mit den FileChannel zu handieren (was mir ohnehin eigenartig vorkommt).
Das leuchte mir ein und ich werde es auch nicht mehr verwenden.

Mein kleines Projekt sollte einem Benutzer nur die Möglichkeit geben, Daten von A nach B zu kopieren!
Unabhängig ob es Lokale Datenträger oder gemountete FTP-, Netzlaufwerke sind.

Bei besagten Usern handelt es sich meist um ältere Benutzer die Mühe haben mit den neuen Techs.
Diese haben meist schon Probleme mit drag&drop resp. copy/past.
Soll heissen:
  1. Wähle die Ordner / die Dateien aus die Du kopieren möchtest:
  2. Wähle den Ordner aus in dem die Ordner / die Dateien gespeichert werden sollen:
thats all.
Rest erledigt mein kleines Programm.

Man müsste die Software Entwickler dazu bringen, dass solche Dateinamen nicht generiert werden können:
Beispiel: MeinVideo 24.09.18° 1:45''30'.mp4 oder so ähnlich...

Intresannterweise beherschen Konsole-Befehle solche Dateinamen, wenn man sie in Anführungszeichen resp. Hochkomma setzt.
In der Regel verwende ich Anführungszeichen. In Sonderfällen können Hochkommas dienen.

habe ich mir mal angeschaut.

Ich verwende OpenJDKs
Einige Quell-Texte werden mir nicht angezeigt.
Also werde ich immer andere Lösungen suchen.
 
G

Gelöschtes Mitglied 56712

Gast
Sorry wenn ich nochmals damit komme...

Mit folgendem Code kann ich alle Dateien rekursiv auflisten (Dateiname und Grösse ausgeben)
Java:
public void getFileSize(String server, String user, String pass, String remotePath) {
    if(ftpClient == null) {
        ftpClient = new FTPClient();
        ftpClient.setDefaultTimeout(60000);
    }
    try {
        ftpClient.connect(server);
        if(!ftpClient.login(user, pass)) {
            new MyDialog(null, 2, 0, "Loggin-Fehler", new Font("Arial", Font.PLAIN, 14), new String[] {"OK"})
            .confirm("Einloggen <b>Fehlgeschlagen!</b>", "stop");
        }
        FTPFile[] files = ftpClient.listFiles(remotePath);    //.listFiles(remotePath)
        if(files != null) {
            for (FTPFile f : files) {
                if(f.getType() == FTPFile.DIRECTORY_TYPE) {
                    if(f.getName().equals(".") || f.getName().equals("..")) {
                        continue;
                    }
                    String neuRemote = remotePath+ "/" +f.getName();
                    getFileSize(server, user, pass, neuRemote);
                }
                else {
                    tot = getTot() + f.getSize();
                    anzahl = getAnzahl() + 1;
                }
            }
        }
    }
    catch (IOException ex) {
        System.out.println("Error: " + ex.getMessage());
        ex.printStackTrace();
    }
}
Das Problem, dass Ordner welche Leerzeichen (chr32) enthalten, werden zwar angezeigt, aber rekursiv nicht ausgelesen.
Gehe ich auf cPanel-Dateiverwaltung kann ich mir deren Inhalt aber anzeigen lassen mit allen von mir gewünschten Informationen.

Intressanterweise kann ich mit dem FTPClient jetzt aber eine Datei, welche Leerzeichen im Namen enthält, herunterladen.
Ebenso werden komplette Ordner (mit Leerzeichen im Namen) mit Inhalt heruntergeladen.

Die Informationen aus obigem Code benötige ich aber vor dem Download.

Weiss jemand wie ich obigen Code verändern muss um auch den Inhalt aus Ordnern (mit Leerzeichen im Namen) auflisten kann?

Vielen Dank.

PS @Robert Zenz
Hab jetzt die Aussage:
Wobei da vielleicht ein "richtiger" FTP-Client besser waere
glaube ich Verstanden.
 
Zuletzt bearbeitet von einem Moderator:
G

Gelöschtes Mitglied 56712

Gast
Nachtrag:
Ebenso werden komplette Ordner (mit Leerzeichen im Namen) mit Inhalt heruntergeladen.
Stimmt leider nicht!
Der Ordner wird zwar lokal erstellt, aber bleibt LEER.

Die Dateien (mit Leerzeichen im Namen) werden in allen Ordner (welche keine Leerzeichen im Namen enthalten) korrekt heruntergeladen.

Fazit:
FTPClient (und auch die gemounteten FTP-Laufwerke in Dateimanagers wie: Explorer, Caja, Nautilus, etc.) beherrscht (beherrschen) keine Ordner
welche Leezeichen im Namen enthalten!
Ist das korrekt?

Vielen Dank
 

Robert Zenz

Top Contributor
FTPClient (und auch die gemounteten FTP-Laufwerke in Dateimanagers wie: Explorer, Caja, Nautilus, etc.) beherrscht (beherrschen) keine Ordner
welche Leezeichen im Namen enthalten!
Ich habe jetzt nicht alles gelesen, aber wenn ich mich richtig erinnere ist die Antwort von einem FTP-Server wenn du nach der Dateiliste fragst undefiniert. Die meisten liefern ls -l kompatible Ausgaben, aber es koennte sein dass dein Server etwas liefert was die Clients einfach nicht verarbeiten koennen.

Das kannst du aber nur herausfinden in dem du die die Kommunikation mit dem Server ansiehst und was dieser liefert, und dann gegen kontrollierst mit einem anderen Client und was die Clients an Format erwarten.
 
G

Gelöschtes Mitglied 56712

Gast
@mrBrown
Es wirft keine Exeptions, läuft einfach durch...
Java:
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
success = ftpClient.retrieveFile(from, outputStream);
success gibt einfach false zurück.
BufferedOutputStream(new FileOutputStream(localFile)); erstellt zwar den Ordner aber er bleibt halt leer.

@Oneixee5
Werd ich ausprobieren...
"FTP is broken by design"
Hab ich mir fast gedacht.
Den Link werd ich konsultieren. Hoffe dass ich da weiterkomme.
 

KonradN

Super-Moderator
Mitarbeiter
"FTP is broken by design"
Das war, was ich auch schon schreiben wollte. FTP war eine frühe Lösung, die nie den Schritt in die moderne Welt geschafft hat und das durch andere Protokolle komplett abgeschafft wurde.

Aus Sicherheitsgründen könnte man hier noch an FTPS denken - also das FTP wenigstens noch per SSL verschlüsseln, damit nicht jeder mitlesen kann. Aber das macht das Protokoll nicht wirklich besser.

Wenn man sich die Welt heute anschaut, dann wurde FTP im Internet in erster Linie durch HTTP abgelöst. Downloads (aber auch Uploads) finden per HTTP Protokoll statt incl. dem ganzen drum herum, das wichtig ist.

Und wenn es um den reinen Filezugriff geht, dann ist SFTP zu nennen - also SSH File Transfer Protokoll - Zugriff einfach per SSH. Da gibt es dann auch die Lösungen, die Du offensichtlich gerne verwendest: sshfs um einfach auf ein eingehängtes Filesystem zuzugreifen. (Ich selbst neige ehe dazu, smb über SSH zu tunneln. Es gibt halt deutlich bessere Zugriffsmöglichkeiten was dann zu einer höheren Performance führt, sobald es halt kein reines "Ich lese eine Datei komplett" und "ich schreibe eine Datei komplett" sein soll.)

Die Einrichtung ist bezüglich SMB über SSH getunnelt etwas komplexer, da halt das ganze SMB zusätzlich gebraucht wird incl. womöglich dem "Hardening" (smb nur auf localhost hören lassen und in der firewall die Ports zusätzlich sperren, damit da nicht versehentlich das Protokoll heraus gegeben wird.)
 

Oneixee5

Top Contributor
Zusätzlich wäre noch WebDAV zu nennen. Ist mit einem Apache Webserver ziemlich leicht einzurichten aber furchtbar zu programmieren. Man sollte dafür externe Libs verwenden.
 
G

Gelöschtes Mitglied 56712

Gast
@KonradN

Habe Anfänger Thema gewählt, weil dem so ist.

Wie würde denn folgender Code als FTPs aussehen?
Was muss daran geändert werden?
Java:
public void getFileSize(String server, String user, String pass, String remotePath) {
    if(ftpClient == null) {
        ftpClient = new FTPClient();
        ftpClient.setDefaultTimeout(60000);
    }
    try {
        ftpClient.connect(server);
        if(!ftpClient.login(user, pass)) {
            new MyDialog(null, 2, 0, "Loggin-Fehler", new Font("Arial", Font.PLAIN, 14), new String[] {"OK"})
            .confirm("Einloggen <b>Fehlgeschlagen!</b>", "stop");
        }
        FTPFile[] files = ftpClient.listFiles(remotePath);    //.listFiles(remotePath)
        if(files != null) {
            for (FTPFile f : files) {
                if(f.getType() == FTPFile.DIRECTORY_TYPE) {
                    if(f.getName().equals(".") || f.getName().equals("..")) {
                        continue;
                    }
                    String neuRemote = remotePath+ "/" +f.getName();
                    getFileSize(server, user, pass, neuRemote);
                }
                else {
                    tot = getTot() + f.getSize();
                    anzahl = getAnzahl() + 1;
                }
            }
        }
    }
    catch (IOException ex) {
        System.out.println("Error: " + ex.getMessage());
        ex.printStackTrace();
    }
}
Reicht es wenn ich den "server" von ftp. auf ftps. ändere und den Port xxx mitgebe (welcher immer das auch ist) ?
so in etwa: ftpClient.connect(server, port);
Wobei server jetzt ftps.domain.ch heissen würde und
der Port: ???

Oder ist das eine andere Lib für FTPs die ich importieren müsste?

Ich denke für meine Belange würde FTPs reichen.

Wäre schön wenns so einfach klappen täte.
Sonst wären das bei meinen Kenntissen wieder viele Arbeitsstunden.
Gruss Richi
 

KonradN

Super-Moderator
Mitarbeiter
Bei FTPS ändert sich doch nicht der Hostname oder so.

Server haben einen (oder mehrere) Hostnamen. So wie du diverse Namen haben kannst. Da kann man Dich dann ansprechen. Aber natürlich muss man nicht den Namen ändern, wenn man Dich um etwas anderes bittet.

Was sich ändert bei FTPS ist, dass die Verbindung etwas anders aussieht. Unter dem Strich ist es einfach ein Tunnel der FTP Verbindung über SSL. Das muss der Client natürlich können. So das FTPClient die Klasse von apache commons ist: Da wäre für FTPS dann der FTPSClient zu verwenden:

Damit änderst du aber an den genannten Problemen nichts, die Du bei den Zugriffen hattest.
 
G

Gelöschtes Mitglied 56712

Gast
Hallo @KonradN
Damit änderst du aber an den genannten Problemen nichts, die Du bei den Zugriffen hattest.
Beim "normalen" FTP funktioniert es jetzt perfekt mit:
Java:
ftpClient.setAutodetectUTF8(true);
Das hat mit meinen bescheidenen Kenntissen eine ganze Weile gedauert, bis ich das rausgefunden habe.

Die Einrichtung ist bezüglich SMB über SSH getunnelt etwas komplexer, da halt das ganze SMB zusätzlich gebraucht wird incl. womöglich dem "Hardening" (smb nur auf localhost hören lassen und in der firewall die Ports zusätzlich sperren, damit da nicht versehentlich das Protokoll heraus gegeben wird.)
Würde bedeuten, dass ich bei den Kunden Ihre Mountgeschichte umschreiben muss.
Wollte ich eigentlich nicht.

So ziemlich alle Linux-Kunden die bis jetzt bei mir nachgefragt haben (Neue und Alte) mounten mit curlftps

Würde sagen, dass sich das Problem damit erledigt hat.

Vielen Dank an Alle die mir geholfen haben.
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Java Themen

Neue Themen


Oben