Re: get() and read() function from fstream
On Feb 4, 8:40 pm, ZikO <ze...@op.pl> wrote:
Im using C++ Compiler as below:
g++ (GCC) 4.3.0 20080305 (alpha-testing) mingw-20080502
Copyright (C) 2008 Free Software Foundation, Inc.
Im writing the simple program which is supposed to give info
about sound wave file. It checks whether a file is a wave
format (4 ASCII bytes should be like {'R','I','F','F'}) and
then it reads what the size of the file is (another 4 bytes).
However, I found difficult to understand how to use both get()
and read() functions properly which are in <fstream> library.
there is the code below in which I check if file starts with
"RIFF". I have used waveFile.get() function to obtain 4 bytes
from the input stream, although I wanted read() before. I had
to use get() because if I used read() instead the program
would go straight to else branch and display "This is not a
wave file", even if it is.
Any suggestions why read() does not work here?
Not really, but there are a number of problems in your code.
[code]
.#include <iostream>
.#include <fstream>
.#include <cstring>
.using namespace std;
.void checkStream(ifstream& in_str) {
. // if() {} ...
. return;
.}
.int main() {
. ifstream waveFile("test.txt");
The wave format contains binary data, so you must open the file
in binary mode. Otherwise, your code will only work on Unix and
Unix look-alikes (where binary and text modes are identical).
std::ifstream waveFile( "test.txt", std::ios::binary ) ;
(Also, .txt is a very strange filename ending for a binary file.
If you're dealing with wave files, I'd expect something like
..wav.)
And are you sure the open succeeded. You need to test the
status immediately:
if ( ! waveFile ) {
fatalError( "cannot open test.txt" ) ;
}
. int filePointer = 0;
Almost certainly not a problem in your tests, but int is
generallly not big enough to hold a position in a file. I'd use
either std::streampos or long long.
. char temp[5] = {0,0,0,0};
Just {} would be sufficient. Interestingly enough the only byte
you really need initialized is the last, which is the only one
you don't initialize explicitly (but as soon as the initializer
list is present, all elements without an explicit initializer
are initialized as 0.
. if(waveFile.get(temp,4)) {
. // cout << "stream pointer = " << waveFile.tellg() << endl;
. filePointer += 4;
. char waveChunk[] = {"RIFF"};
. if(strcmp(temp, waveChunk)) {
What's wrong with just strcmp( temp, "RIFF" ) ?
. cout << "This is a wave file." << endl;
. }
. else {
. cout << "This is not a wave file" << endl;
. return 0;
. }
. }
. else
. checkStream(waveFile);
. int roz;
. waveFile.seekg(filePointer);
. if(waveFile.read(reinterpret_cast<char*>(&roz), 4)) {
And this won't necessarily work. You can't just read raw binary
data. You have a binary file with a specific format. That
format isn't directly supported by the standard, so you have to
implement it yourself.
From what little information I've found, you need to do
something like:
unsigned long
readWaveInt(
std::istream& source )
{
unsigned long result = 0 ;
for ( int shift = 0 ; shift != 32 ; shift += 8 ) {
result |= source.get() << shift ;
}
return result ;
}
(This will return some random value if you encounter EOF within
the function, but in this case, the call to get should set
failbit, so you can detect the error by testing source.)
Note that this is *not* the usual external format for an int.
. filePointer += 4;
. roz += 8;
. cout << "The size is: " << roz << endl;
. }
. else
. checkStream(waveFile);
.}
[/code]
If this code outputs "This is not a wave file", either you've
not successfully opened the file, or the first four bytes aren't
"RIFF" (or you're on a platform where the native character
encoding isn't an extension of ASCII, but that's highly
unlikely---I don't think you'd be reading wave files on a
mainframe).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34