PDA

View Full Version : programma fatto in java per copiare foto


int_double
18-05-2007, 18:11
salve a tutti questo è il mio primo post, potete per favore darmi una mano a fare questo programma in java perchè sono in difficoltà:
dovrei fare un programma che verifica se un immagine esiste in una directori e la copia nella stessa ma con un nome diverso (esempio foto1.bmp ne crea un'altra di nome copia.bmp) inoltre il programma deve fare una test: l'immagine di partenza esiste?
- se si verifica che non esiste già una foto con il nuovo nome che si vuole dare e in quel caso chiede se sovrascriverla, inoltre quando ha finito la copia avvisa
- se non esiste l'immagine di partenza avvisa l'utente che non l'ha trovata e saluta

ho provato questo codice ma la nuova immagine presenta dei difetti :mc:

ciao, mi aiutate per favore :help:

int_double
18-05-2007, 18:12
salve a tutti questo è il mio primo post, potete per favore darmi una mano a fare questo programma in java perchè sono in difficoltà:
dovrei fare un programma che verifica se un immagine esiste in una directori e la copia nella stessa ma con un nome diverso (esempio foto1.bmp ne crea un'altra di nome copia.bmp) inoltre il programma deve fare una test: l'immagine di partenza esiste?
- se si verifica che non esiste già una foto con il nuovo nome che si vuole dare e in quel caso chiede se sovrascriverla, inoltre quando ha finito la copia avvisa
- se non esiste l'immagine di partenza avvisa l'utente che non l'ha trovata e saluta

ho provato questo codice ma la nuova immagine presenta dei difetti :mc:

ciao, mi aiutate per favore :help:

scusate ecco il codice:

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Copia {
public static void main(String[] args) throws IOException {
File inputFile = new File("foto1.bmp");
File outputFile = new File("nuova.bmp");
FileReader in = new FileReader(inputFile);
FileWriter out = new FileWriter(outputFile);
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close();
out.close();
}
}

franksisca
18-05-2007, 18:52
non ho il tempo di contyrollarlo ora, ma la nuova immagine, che difetti presenta????


a che ti serve, magari possiamo darti una mano a fare qualcosa di più carino:D

PGI-Bis
18-05-2007, 19:02
La faccio breve. Idea corretta, strumenti errati. Esempio con commento passo-passo:

package int_double.copyimage;

import java.io.*;
import java.nio.channels.*;

//Java 6 Required
public class Main {

public static void main(String[] args) {
String directory = ".";//System.getProperty("user.dir");
//immagine inella directory di lavoro
String nomeFile = "foto1.bmp";

//esiste?
File file = new File(directory + File.separator + nomeFile);
boolean esiste = file.exists();

//se esiste, crea la copia
if(esiste) {
try {
copiaFile(directory, "foto1.bmp", "copia.bmp");
System.console().printf("File copiato.%n");
} catch(IOException ex) {
System.console().printf("Errore durante la copia.%n%s%n", ex);
}
} else {
System.console().printf("Il file da copiare non esiste.%n");
}
}

/**Questo è il metodo che copia il file nomeFile, nella directory
directory, sul file nomeCopia, nella stessa directory */
private static void copiaFile(String directory, String nomeFile,
String nomeCopia) throws IOException
{
/** Crea un riferimento al file da copiare */
File fileDaCopiare = new File(directory + File.separator + nomeFile);

/** Crea un riferimento al file su cui copiare. Non crea il file: il file
vero e proprio è creato da FileChannel quando si inizierà a scrivere. */
File nuovoFile = new File(directory + File.separator + nomeCopia);

/** Canale da cui provengono i byte da copiare */
FileChannel in = null;

/** Canale da cui usciranno i byte */
FileChannel out = null;
try {
/** Apre un canale sul file da copiare */
in = new FileInputStream(fileDaCopiare).getChannel();

/** Apre un canale in uscita sul file copiato */
out = new FileOutputStream(nuovoFile).getChannel();

/** Copia tutti i byte del file in entrata sul file in uscita */
long byteScritti = 0;
long byteTotali = in.size();
while(byteScritti < byteTotali) {
byteScritti += out.transferFrom(in, byteScritti, byteTotali);
}
} finally {
close(in, out);
}
}

private static void close(Channel in, Channel out) throws IOException {
try {
if(in != null) in.close();
} finally {
if(out != null) out.close();
}
}
}

Con i flussi i metodi copiaFile e close diventerebbero:

private static void copiaFileConFlussi(String directory, String nomeFile,
String nomeCopia) throws IOException
{
/** Crea un riferimento al file da copiare */
File fileDaCopiare = new File(directory + File.separator + nomeFile);

/** Crea un riferimento al file su cui copiare. Non crea il file: il file
vero e proprio è creato da FileChannel quando si inizierà a scrivere. */
File nuovoFile = new File(directory + File.separator + nomeCopia);

FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(fileDaCopiare);
out = new FileOutputStream(nuovoFile);
int byteLetto;
while((byteLetto = in.read()) != -1) {
out.write(byteLetto);
}
} finally {
close(in, out);
}
}

private static void close(InputStream in, OutputStream out)
throws IOException
{
try {
if(in != null) in.close();
} finally {
if(out != null) out.close();
}
}

In verità useresti BufferedInputStream e BufferedOutputStream anzichè direttamente FileInputStream e FileOutputStream. Ma è un caso scolastico: per questo genere di operazioni i flussi sono relitti del passato.

int_double
18-05-2007, 20:28
grazie per l'aiuto PGI-Bis :)

mi puoi spiegare per favore
1) cosa è File.separator, la barra \ per caso?
2) byteScritti += out.transferFrom(in, byteScritti, byteTotali);
3) mi puoi dire come fare per vedere se il file chè andro a scrivere esiste già e mi chiede sovrascriverlo S/N?

ma questo codice funziona soltanto con java 6 perchè io ho la versione 5 e con il 56k :muro: ...


grazie tanto :)

PGI-Bis
18-05-2007, 21:10
Per 1.5 sostituisci "System.console().printf(" con "System.out.printf". Il resto dovrebbe essere uguale.

Sì, File.separator è la barra. \ su Windows, / su Unix.

Il metodo transferFrom di FileChannel richiede tre argomenti.

Il primo è un ReadableByteChannel che rappresenta la sorgente dei dati da cui il canale trasferirà i byte (transfer from, trasferisci da). Nel codice ho usato "in". "in" è il FileChannel aperto sul file da copiare.

Il secondo parametro è un intero long. Questo intero stabilisce la posizione a partire dalla quale il canale deve scrivere i dati sul file in uscita. Ad esempio se quel numero valesse 3000 allora i byte verrebbero scritti a partire dalla posizione 3000. Se valesse 0 allora il trasferimento scriverebbe i byte a partire dalla posizione 0 (che è l'inizio del file di destinazione).

Il terzo parametro è un altro intero long. Questo intero stabilisce il numero massimo di byte che possono essere trasferiti dal canale sorgente. Se valesse 3 allora l'operazione "transferFrom" trasferirebbe al massimo 3 byte. Nel codice vale "in.size()". Per un FileChannel il metodo size() restituisce il numero di byte totali conservati nel file.

L'invocazione transferFrom è dentro ad un ciclo while. In pratica quel ciclo è superfluo. Si potrebbe dire:

out.transferFrom(in, 0, in.size());

e funzionerebbe benissimo. Non è superfluo in teoria. La documentazione del metodo trasferFrom dice che è possibile che il trasferimento non si concluda in un'unica tranche. Il metodo trasferFrom restituisce un valore long corrispondente al numero di byte effettivamente trasferite dall'operazione. Il ciclo while dell'esempio usa questo numero per incrementare un contatore e ripete l'operazione transferFrom finchè quel contatore non ha un valore pari al numero di byte presenti nel file di origine. Nel caso in cui il trasferimento non si concluda con una singola invocazione di transferFrom, le invocazioni successive devono tener conto del fatto che i byte da aggiungere al file di destinazione dovranno essere scritti a partire da dove è stato scritto l'ultimo byte dell'invocazione precedente. Se usassi il valore 0 e il trasferimento richiedesse due invocazioni allora la seconda sovrascriverebbe in tutto o in parte la prima. Passandogli il numero di byte precedentemente scritti ottengo invece il corretto accumulo dei dati.

L'ultimo parametro è sempre uguale (e non si riduce con l'incremento dei byte trasferiti) perchè la documentazione dice che questo è un valore massimo di byte trasferibile e non la quantità che dovrà effettivamente essere trasferita. Presumibilmente questo terzo long è usato per allocare un buffer tampone. Per grandi file potrebbe essere sensato stabilire un valore ottimale tipo 512 o 1024 byte.

Aggiungere la richiesta di conferma non è complicato. E' una cosa che probabilmente andrebbe fatta con un po' più di eleganza ma siamo sul procedurale per cui proseguo con questa strada.

package int_double.copyimage;

import java.io.*;
import java.nio.channels.*;
import java.util.*;

public class Main {

public static void main(String[] args) {
String directory = ".";//System.getProperty("user.dir");
//immagine inella directory di lavoro
String nomeFile = "foto1.bmp";

//esiste?
File file = new File(directory + File.separator + nomeFile);
boolean esiste = file.exists();

//se esiste, crea la copia
if(esiste) {
try {
confermaECopia(directory, "foto1.bmp", "copia.bmp");
} catch(IOException ex) {
System.out.printf("Errore durante la copia.%n%s%n", ex);
}
} else {
System.out.printf("Il file da copiare non esiste.%n");
}
}

private static void confermaECopia(String directory, String nomeFileSorgente,
String nomeFileDestinazione) throws IOException
{
File fileDaCopiare = new File(directory + File.separator + nomeFileSorgente);
File fileDestinazione = new File(directory + File.separator + nomeFileDestinazione);

boolean destinazioneEsiste = fileDestinazione.exists();
boolean scrivi = true;

/* Se il file di destinazione esiste allora devo chiedere una conferma */
if(destinazioneEsiste) {
String messaggio =
"Nella cartella %s esiste gia' un file di nome %s," +
" Devo sovrascriverlo? [Si'/No] > ";
Scanner input = new Scanner(System.in);

boolean attendiInput = true;
do {
/* Stampa il messaggio che accompagna la richiesta di input*/
System.out.printf(messaggio, directory, nomeFileDestinazione);

/* Prende la linea di input digitata dall'utente */
String line = input.nextLine();

/* Se il testo di quella linea è "no", a meno di capitalizzazioni... */
if(line.equalsIgnoreCase("no")) {
scrivi = false;
attendiInput = false; //causa uscita dal ciclo
} else if(line.equalsIgnoreCase("si")) {
/* Se invece il testo è si... */
scrivi = true;
attendiInput = false; //causa uscita dal ciclo
}
} while(attendiInput);
}

/* Se il file di destinazione non esiste allora scrivi vale "true" in
partenza. Se il file di destinazione esiste allora scrivi vale, per effetto
del ciclo di input, "true" se l'utente abbia digitato si, "false" se l'utente
abbia digitato no. */
if(scrivi) {
copiaFile(directory, nomeFileSorgente, nomeFileDestinazione);
System.out.printf("File copiato.%n");
} else {
System.out.printf("Operazione annullata.%n");
}
}

/**Questo è il metodo che copia il file nomeFile, nella directory
directory, sul file nomeCopia, nella stessa directory */
private static void copiaFile(String directory, String nomeFile,
String nomeCopia) throws IOException
{
/** Crea un riferimento al file da copiare */
File fileDaCopiare = new File(directory + File.separator + nomeFile);

/** Crea un riferimento al file su cui copiare. Non crea il file: il file
vero e proprio è creato da FileChannel quando si inizierà a scrivere. */
File nuovoFile = new File(directory + File.separator + nomeCopia);

/** Canale da cui provengono i byte da copiare */
FileChannel in = null;

/** Canale da cui usciranno i byte */
FileChannel out = null;
try {
/** Apre un canale sul file da copiare */
in = new FileInputStream(fileDaCopiare).getChannel();

/** Apre un canale in uscita sul file copiato */
out = new FileOutputStream(nuovoFile).getChannel();

/** Copia tutti i byte del file in entrata sul file in uscita */
long byteScritti = 0;
long byteTotali = in.size();
while(byteScritti < byteTotali) {
byteScritti += out.transferFrom(in, byteScritti, byteTotali);
}
} finally {
close(in, out);
}
}

private static void close(Channel in, Channel out) throws IOException {
try {
if(in != null) in.close();
} finally {
if(out != null) out.close();
}
}
}

Se per caso è il codice di un esercizio scolastico non incollare quello che ho scritto perchè ti beccano subito.

int_double
19-05-2007, 10:22
PGI-Bis sei grande!
grazie tanto :)