Newsgroup: it.comp.lang.c++
Titolo: ifstream.

Voglio fare un semplice programmino in cui leggo dei dati da un file e
vi eseguo sopra delle elaborazioni. Normalmente avrei usato le API Win32
(CreateFile e ReadFile) e ci avrei messo due minuti, ma siccome il
programmino č breve e veloce ho pensato di usare ifstream a mo' di
esercizio. E' piů di un ora che ci provo e non ci riesco. Questo č
quello che ho scritto e davvero non capisco perché non funzioni. Spero
che mi aiuterete.
FBF
#include <fstream>
#include <iostream>
#include <assert.h>
using namespace std;
const char* lpszFile = "Androm.bmp";
const unsigned int bufsize = 1024;
main()
{
 ifstream i(lpszFile);
 assert(i.is_open());
 char buf[bufsize];
 unsigned int byte_counter = 0;
 while (! i.eof())
 {
  i.read(buf, bufsize);
  byte_counter += bufsize;
  cout << ':' << byte_counter << '\n';
 }
 return 0;
}
opss! Dimenticavo di dire perché non funziona. Esegue la prima lettura e
poi pensa di essere arrivato alla fine del file, anche se questo č di
circa 80k e lui dovrebbe aver appena letto il primo kb.

  ifstream i(lpszFile);
Stai aprendo un file binario e quindi devi specificare
ifstream i(lpszFile, ios::in | ios::binary);
Comunque, compilato con il DJGPP pare funzionare perfettamente anche
senza la modifica di cui sopra.
EMG

 ifstream i(lpszFile);
Con qualche compilatore occorre:
ifstream(lpszFile, ios::in | ios::binary); 
che pero' non dovrebbe essere necessario
con compilatori piu' aderenti allo standard.
HTH, Aldo
--
Is everybody in? Is everybody in?
The ceremony is about to begin.
                        (Jim Morrison)

 con compilatori piu' aderenti allo standard.
Vuoi dire che lo standard ha cambiato il default per la modalità di
apertura dei files da testo a binario?
EMG



No. Lo standard non ha cambiato alcunche':
[lib.ifstream] 27.8.1.5               Template class basic_ifstream
namespace std {
 template <class charT, class traits = char_traits<charT> >
  class basic_ifstream : public basic_istream<charT,traits> {
     public:
     .... 	
      // 27.8.1.6 Constructors:
     ....
     explicit  basic_ifstream(const char* s,
                             ios_base::openmode mode =ios_base::in);
     ....
  };
  // typedef basic_ifstream<char> ifstream;
}
Tuttavia alcuni compilatori, per esempio VC++6.0 e gcc 2.95,
sembrano usare correttamente la ifstream::read(char*,streamsize)
solo se il file e' aperto come file binario mentre lo standard non lo
richiede affatto, almeno credo. Quindi questi compilatori non sono
conformi allo standard.
E' utile usare  la ifstream::read(char*,streamsize) su un file aperto
in modalita' testo? Problemi del programmatore, non della funzione.


 No. Lo standard non ha cambiato alcunche':
Si, ora ho capito: l'effetto della modalità di apertura dovrebbe essere
system-dependent. Ad esempio, in MS-DOS i due caratteri CR-LF vengono
letti come un unico carattere '\n' in modalità testo e come '\r' e '\n'
in modalità binaria. In questo caso, qual'è il default per gli input
streams? Sbaglio qualcosa?
EMG

cosa succede se leggo un CR-LF?
Indipendentemente dalla modalita' di apertura, il filebuf
associato con l'ifstream viene riempito con una copia
esatta dei primi SIZE caratteri del file, dove SIZE e' la
implementation defined dimensione del filebuf.
Quindi in esso sono presenti le sequenze CR-LF se,
per esempio, pippo.txt e' un file ms-dos.
<inizio file ms-dos pippo.txt>
01234CR-LF
56789CR-LF
<fine file ms-dos  pippo.txt> // totale 14 caratteri
<inizio filebuf>
01234CR-LF56789CR-LF<EOF>..............
<fine   filebuf> // capacita' SIZE caratteri
                          // contenuto fisico 14 caratteri + <EOF>
I flags d'apertura, ios::in e ios::binary, "avvertono" tutte
le operazioni di lettura su tale filebuf, che avvengono
tramite l'interfaccia dell 'ifstream che le inoltra ad esso,
se effettuare o meno la mappatura logica:
CR-LF  --> '\n'  // il carattere C/C++ newline
Mappatura NON modifica: il '\n' occupa sempre DUE
caratteri nel filebuf che pero' sono logicamente visti
come un solo carattere.
Con ios::in tale mappatura viene attivata,
con ios::in | ios::binary no!
Quindi se std::ifstream ifs("pippo.txt"); // default ios::in
le funzioni di lettura dell'oggetto ifs, "vedono" il conte-
nuto del filebuf cosi':
<inizio filebuf>
01234'\n'56789'\n'<EOF>..............
<fine   filebuf> // capacita' SIZE caratteri
                          // contenuto logico 12 caratteri + <EOF>
                          // contenuto fisico  14 caratteri + <EOF>
Se std::ifstream ifs("pippo.txt, ios::in | ios::binary ) lo
vedono invece nella forma grezza.
<inizio filebuf>
01234CR-LF56789CR-LF<EOF>..............
<fine   filebuf> // capacita' SIZE caratteri
                          // contenuto logico 14 caratteri + <EOF>
                          // contenuto fisico  14 caratteri + <EOF>
Ovviamente se il file ha dimensione maggiore di SIZE,
dopo che il programma ha consumato nel modo visto
prima il suo contenuto, lo svuota e lo riempie con i
successivi SIZE caratteri del file e cosi' via.
Mi accorgo ora di essere stato forse un po' troppo
prolisso e me ne scuso, ma talvolta il solo scrivere
qualche cosa aiuta lo stesso scrivente a schiarirsi
le idee, almeno spero!
Aldo.


 prolisso
Solo un tantinello. :-)))
EMG

conformi allo standard.
Il Borland richiede il binary (l'unico parametro di default e'
ios::in).
Bye.

ios::in).
Queste cose sono il minimo... specificare la modalita` di apertura e 
lettura di un file sempre e comunque non puo` che essere una buona
pratica di defensive programming.
I parametri di default sono una gran cosa, ma se c'e` di mezzo qualche 
standard a cui la libreria non aderisce al 100% e` bene prendere
precauzioni.
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

precauzioni.
Difatti io sin da quando programmavo in Basic e Turbo Pascal ho sempre
evitato i parametri di default almeno nelle operazioni di I/O (non si
mai!!!). Mi sembra piu' un vantaggio sia per chi ha costruito il
codice sia per chi se lo deve andare a leggere (e correggere). Per non
parlare poi se ogni compilatore vuole definire un proprio standard...
Bye.

parlare poi se ogni compilatore vuole definire un proprio standard...
In questo caso il problema e` diverso, non essendoci uno standard di
riferimento ognuno fa a modo suo, da questo il problema.
Non si tratta dunque di una cosa intrinseca nei parametri di default.
