Newsgroup: it.comp.lang.c++
Titolo: altro problema con fstream

Eseguo la copia di un file semplicemente facendo:
while (fin.read(buffer, sizeof buffer))
    fout.write(buffer, sizeof buffer);
Ma mi sapete spiegare perchč NON viene letto (o scritto) l'ultimo byte del
file?
Cosa sbaglio stavolta?
Inoltre io dichiaro buffer come:
char *buffer;
E poi faccio: buffer=new char[1000];
Facendo perņ un cout << sizeof buffer ;  ottengo con mia sorpresa 4! Ma
perchč se io lo ho impostato a 1000?
Grazie mille per l'attenzione,
Alex
--
------------------
email: el_co...@TOGLIQUESTOlibero.it
icq: 132581870
------------------


Nulla :P


 Non puoi usare la dimensione di una qualsiasi area di memoria se e' stata
Ehm , non era "Usare"  :P
Era "Non puoi sapere la dimensione di una qualsiasi area di memoria ..."
Scusate :P



Guardando l'MSDN del VC++ e constatandolo di persona copiando un file di
170Mb la funzione in sostanza copia prima nella ram tutto il file e poi
restituisce un puntatore all'area di mem occupata.
Io preferivo copiare un file in + passaggi, in parti da 100k (vedi post
sopra).
Grazie per la risp cmq.
Ciao,
Alex

 >     fout.write(buffer, sizeof buffer);
Come potrai verificare tu stesso la funzione scrive 2byte in piů.
Ma credo di aver capito dove č il problema:
Correggimi se sbaglio. Come mi hai spiegato te prima la funzione sizeof
viene risolta al momento della compilazione.
Quindi si passa alla funzione read e poi alla write 4 (perchč un puntatore č
un indirizzo a 32bit in modo protetto). Quindi si copia il file in parti
da 4 byte e NON in parti da 1000. E quando io arrivo alla fine del file io
passo alla funzione read 4; questa perň fallisce dato che mancano solo
2byte da leggere ed ecco perchč nella copia del file mancano 2 byte (non 1
come avevo detto, mi ero sbagliato).
Infatti se io copio un file la cui dimensione č divisibile per 4 la copia č
perfetta!
Ho risolto il problema cosě:
while (fin.read(buffer,1000)) {
      fout.write(buffer, 1000); }
 templ=fin.tellg();
 fin.seekg (fout.tellp());
 templ=templ-fout.tellp();
 fin.read(buffer,templ);
 fout.write(buffer,templ);
Facendo cosě vedo in che byte si č fermata la funzione write ( tellp). Poi
in sostanza ricavo la dimensione di fin (che equivale alla posizione della
testina di fin.get). Sottraggo cosě vedo quanti byte mancano effettivamente
da scrivere e li passo alla funzione read e poi write che si svolgono senza
errori. Qualsiasi dimensione abbia il file esso viene copiato esattamente,
in pezzo da 1000 byte.
Spero di non aver scritto stupidaggini anche se non me ne sembra.
Grazie mille  per l'aiuto,
Alex

  fout.write(buffer,templ);
	Ma il sempreverde...
char c;
while( fin.get(c) ) fout.put(c);
...? Lo scartavi per motivi di efficienza?
_dave_

 ...? Lo scartavi per motivi di efficienza?
Sì.
-- 
-----------     
email: el_co...@TOGLIQUESTOlibero.it
icq: 132581870
-----------

Sir 13h (Alex) wrote:
   > Guardando l'MSDN del VC++ e constatandolo di persona copiando un
   > file di 170Mb la funzione in sostanza copia prima nella ram tutto
   > il file e poi restituisce un puntatore all'area di mem occupata.
Penso che dipenda dall'implementazione: con g++/linux ho provato a
copiare un file di circa 260MB e (se top non mente) non sembra usare
molta piu` memoria di un 'Hello World'.
   > Io preferivo copiare un file in + passaggi, in parti da 100k (vedi
   > post sopra).
Comunque si`, il tuo approccio e`, in generale, il migliore, visto che
copre anche le eventuali mancanze di una libreria C++ non ottimale.
(Inutile sprecare neuroni ad inveire contro le implementazioni poco 
standard, meglio usarli per trovare degli eleganti `workaround' :-) )
Ciao


Sir 13h (Alex) wrote:
 > Ho risolto il problema così:
 >
 > while (fin.read(buffer,1000)) {
 >       fout.write(buffer, 1000); }
 >  templ=fin.tellg();
Qui c'e` un problema.
Compilando con g++ 2.95.3, tutto sembra andar bene: viene restituito
il valore della posizione dell'ultimo byte, aumentato di 1 (cioe` la
dimensione del file).
Compilando con g++ 3.2, la chiamata a `tellg' restituisce (sopresa!)
un bel `-1' (che sembra dovuto al fatto che l'accesso al byte oltre la
fine del file fallisca, o al fatto che `fin.fail()' sia vero).
Non so cosa dica lo Standard a proposito; forse, senza volerlo,
abbiamo oltrepassato l'inviolabile confine dell'Undefined Behavior ;-)
Prova a stravolgere tutto, calcolando prima la dimesione del file.
Quindi copi tutti i blocchi interi e, infine, lo spezzone che rimane.
<code>
const int block_size = 4096;	// Dimensione del blocco
char buffer[block_size];
 
std::ifstream fin("input_file");
std::ofstream fout("output_file");
// Calcola la dimensione del file...
fin.seekg(0, std::ios::end);
std::streampos file_size = fin.tellg();
// ...quindi si ricorda di riportare la testina all'inizio!
fin.seekg(0, std::ios::beg);
// Dimensione dello spezzone che rimane oltre l'ultimo blocco
int remainder = file_size % block_size;
 
while (fin.read(buffer, block_size))
	fout.write(buffer, block_size);
if (remainder != 0) {
	// Copia l'ultimo spezzone
	fin.seekg(-remainder, std::ios::end);
	fin.read(buffer, remainder);
	fout.write(buffer, remainder);
}
</code>
L'ho provato su diversi file con dimensioni < block_size,
== block_size, == block_size + 1, == 2*block_size - 1,
  >> block_size.
Sembra che funzioni, senza caricare file interi in memoria o copiare
inefficientemente carattere per carattere.


  templ=fin.tellg();
Qui c'e` un problema.
