Reading RAW audio file - c++

I am a beginner in C++ and I have a school project implying analysing an audio file and I can't read the file, in the example the program keeps reading the first value from the file
#include <iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream c;
c.open("cv.RAW");
int b;
while(1)
{
c>>b;
cout<<b<<" ";
}
return 0;
}

you need to
open your file in binary mode ifstream c("cv.RAW", std::ios_base::binary), if you read a binary file without this flag it will be treated as a text file and will give you incorrect values.
check the file is open by checking if (c.good()) or just if (c) before reading any values
check the reads succeed by again checking if (c.good()) or just if (c) after reading each byte
read using c.read((char*)&b, sizeof(b)) if you want to read an integer at a time, for a single byte use char ch; c.read(&ch, sizeof(ch))
iostreams don't throw exceptions by default so you always need to check their state every time you use them.

Related

Set integer variable through file read

I know how to pass in strings from a text file. In a previous project I read in strings and then tested them on either being "t" or "f", which the result of would set a variable to true or false.
Now I am wondering if it is efficiently possible to read numbers from a text file and pass them into an int? All I can think of is checking for the string "1" and returning 1 in a function, but that would have to be done for every possible integer I could expect in my program, which is not an effective solution.
For context, I am trying to make a save system for a game, and ints/floats that are read in would be variables such as player health, how much of an item they have, etc.
If you already know how to read a string str from a text file, reading numbers is not that difficult: jsut read the string as you did and use stoi() to convert the string into an int, or stof() into float.
int i; double d;
i=stroi(str); d=strod(str2);
Another technique is to use file streams to read or write from a file exactly as you would do from cin and cout:
ifstream file("mytext.txt");
file>>i>>d;
The previous method doesn't care so much about lines. So still another technique is to read a string, convert it into a string stream and use the stringstream as you would with cin:
if (getline(file, str)){ // read a full line
stringstream sst(str);
sst>>i>>d;
}
Using std::fstream. You can open a file, and stream input or output based on how you opened the file.
Example:
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
// Pretend we are passed the file location as a command-line argument to our program:
std::fstream file { argv[1], std::ios::in };
if (file.is_open())
{
int value;
file >> value;
std::cout << value << std::endl;
}
else
{
std::cout << "Could not open file " << argv[1] << std::endl;
}
}
Provided that the information is correctly formatted in the file, this should work.
I didn't run it, so there might be syntax errors, but the basics are there. Check out cppreference for some help, they will have further examples.

visual studio c++ cin big string from command line

When I run the following program and paste 50000 symbols to the command line, the program gets 4096 symbols only. Could you please suggest me what to do in order to get the full list of symbols?
#include <iostream>
#include <string>
using namespace std;
int main()
{
char temp[50001];
while (cin.getline(temp, 50001, '\n'))
{
string s(temp);
cout << s.size() << endl;
}
return 0;
}
P.S.
When I read the symbols from file using fstream, it's OK
I'm taking a leap jump here but since many powershell terminals have 4096 truncation limits (take a look at the Out-File documentation), this is likely a Windows command line limitation rather than a getline limitation.
The same problem has been encountered previously by others: https://github.com/Discordia/large-std-input/blob/master/LargeStdInput/Main.cpp
I don't understand why you are reading into a character array, then transferring it into a string.
In any case, your issue may be with repeated allocations.
Reading into std::string directly
Two simple lines:
std::string s;
getline(cin, s, '\n');
Reading into an array first
Yes, there is a simpler method:
#define BUFFER_SIZE 8196 // Very important, named constant
char temp[BUFFER_SIZE];
cin.getline(temp, BUFFER_SIZE, '\n');
// Get the number of characters actually read
unsigned int chars_read = cin.gcount();
std::string s(temp, chars_read); // Here's how to transfer the characters.
Using a debugger, you need to view the value in chars_read to verify that the quantity of characters read is valid.
Binary reading
Some platforms provide translations between the data read and your program. For example, Windows uses Ctrl-Z as an EOF character; Linux uses Ctrl-D.
The input data may use UTF encoding and contain values outside the range of ASCII printable set.
So, the preferred method is to read from a stream opened in binary mode. Unfortunately, cin cannot be opened easily in binary mode.
See Open cin in binary
The preferred method, if possible, is to put the text into a file and read from the file.

read and write a binary file in c++ with fstream

I'm trying to write simple c++ code to read and write a file.
The problem is my output file is smaller than the original file, and I'm stuck finding the cause.
I have a image with 6.6 kb and my output image is about 6.4 kb
#include <iostream>
#include <fstream>
using namespace std;
ofstream myOutpue;
ifstream mySource;
int main()
{
mySource.open("im1.jpg", ios_base::binary);
myOutpue.open("im2.jpg", ios_base::out);
char buffer;
if (mySource.is_open())
{
while (!mySource.eof())
{
mySource >> buffer;
myOutpue << buffer;
}
}
mySource.close();
myOutpue.close();
return 1;
}
Why not just:
#include <fstream>
int main()
{
std::ifstream mySource("im1.jpg", std::ios::binary);
std::ofstream myOutpue("im2.jpg", std::ios::binary);
myOutpue << mySource.rdbuf();
}
Or, less chattily:
int main()
{
std::ofstream("im2.jpg", std::ios::binary)
<< std::ifstream("im1.jpg", std::ios::binary).rdbuf();
}
Two things: You forget to open the output in binary mode, and you can't use the input/output operator >> and << for binary data, except if you use the output operator to write the input-streams basic_streambuf (which you can get using rdbuf).
For input use read and for output use write.
There are 3 problems in your code:
1- You have not opened your output file in Binary.
2- Your code return "1", normally you should return "0", if something went wrong then return an error code.
3- You should use "manipulators" and make c++ not to avoid whitespaces, so in order to read from file instead of:
mySource >> buffer;
you should use:
mySource >> std:noskipws >> buffer;
Well, its just because of padding at the end of the image. eof of any file do not include the padded bytes added at the end of file.
Try this
take img1.jpg contains 20 space charecter at the end not visible here (uegfuyregwfyugwrerycgerfcg6ygerbucykgeugcrgfrgeyf ) and run your program (do not include parenthesis in the file, these are used to show the data content)
you will see img2.jpg contains (uegfuyregwfyugwrerycgerfcg6ygerbucykgeugcrgfrgeyf)
So, its better option to read the file byte by byte using the filesize which you can get using stat, and run for loop till filesize. Hope this should resolve your problem you mentioned above

seekp before writing?

I want to read and write an binary file with a single file stream. The following code tries to read the first part of the file, and uses it to overwrite the second part of the file. But I find that I have to use "seekp(pos [,ios_base::begin]);" before writing. Additionally, "seekp" in fact doesn't change the position in my code, but it is necessary! Could any one give an explain? It should better be according to the c++ standard. Thanks very much!
#include <iostream>
#include <fstream>
using namespace std;
int main(){
fstream flib ("tmp.txt", ios::in | ios::out |ios::binary | ios::trunc);
if(!flib){
cerr << "file open failed!" << endl;
return 1;
}
int tmp;
for(int i = 0; i<2 ; i++){//write 2 numbers
flib.write((char*)&i, sizeof(tmp));
}
flib.seekg(0);
while(flib.read((char*)&tmp, sizeof(tmp))){//read file contents
cout <<tmp<<endl;
}
flib.clear();
flib.seekg(0);
flib.read((char*)&tmp, sizeof(tmp));
flib.seekp(sizeof(tmp)); //work
//flib.seekp(sizeof(tmp), ios_base::beg); //work
//flib.seekp(0, ios_base::cur); //not work
//flib.seekp(sizeof(tmp), ios_base::end); //not work
//flib.seekp(-sizeof(tmp), ios_base::end); //not work
flib.write((char*)&tmp, sizeof(tmp));
flib.clear();
flib.seekg(0);
while(flib.read((char*)&tmp, sizeof(tmp))){//read file contents
cout <<tmp<<endl;
}
return 0;
}
Comment: I find that if I use flib.seekp(some_number, ios_base::cur); with nonzero some_number, it works. And I use vs2012 express compiler, is it a bug?
File streams use a basic_filebuf<> for the stream buffer. The C++03 standard has this to say about class basic_filebuf<charT,traits>:
27.8.1.1 Class tempate basic_filebuf
The class basic_filebuf associates both the input
sequence and the output sequence with a file.
The restrictions on reading and writing a sequence controlled by an
object of class basic_filebuf are the same as for
reading and writing with the Standard C library FILEs.
In particular:
- If the file is not open for reading the input sequence cannot be read.
- If the file is not open for writing the output sequence cannot be written.
- A joint file position is maintained for both the input sequence and the output sequence.
Unfortunately it doesn't call out that when transitioning between reading and writing to a FILE object using the standard C library, you have to perform a file positioning call (or an fflush() when transitioning from write operations to read operations). See https://stackoverflow.com/a/14879076/12711.

overwriting some text in a file using fstream and delete the rest of the file

I am trying to write a program that read a file using fstream
then, rewrite some of the text and delete the rest of the file
This the code that I am trying to do
#include<iostream>
#include<fstream>
using namespace std;
int main(int argc, char **argv){
fstream *binf;
fstream someFile("t.txt", ios::binary|ios::out|ios::in);
int i;
for(i=0;i<3;i++){
char c;
someFile.seekg(i);
someFile.get(c);
cout<<"c:"<<c<<endl;
}
someFile.seekp(i++);
someFile.put("Y");
someFile.seekp(i++);
someFile.put("Y");
//Delete the rest of the file
return 0;
}
Note the following flags for opening a file
ios::in Open for input operations.
ios::out Open for output operations.
ios::binary Open in binary mode.
ios::ate Set the initial position at the end of the file. If this flag is not set to any value, the initial position is the beginning of the file.
ios::app All output operations are performed at the end of the file, appending the content to the current content of the file. This flag can only be used in streams open for output-only operations.
ios::trunc If the file opened for output operations already existed before, its previous content is deleted and replaced by the new one.
I try many combinations of these but non of them help me to do what I want
I want to read the file until I find text. If I find the text that I want, I over write it and delete the rest of the file. So, the file should be re-sized to smaller file.
You can't do that with single stream object.
Possible solutions:
Either close your file and call truncate function, :
#include <unistd.h>
int ftruncate(int fildes, off_t length);
int truncate(const char *path, off_t length);
MS Windows version of truncate is _chsize - see http://msdn.microsoft.com/en-us//library/dk925tyb.aspx
int _chsize(
int fd,
long size
);
Or open your file for reading only, read/replace to some stringstream, then put everything to your file this time opened for overwriting:
fstream someFile("t.txt", ios::binary|ios::in);
stringstream ss;
// copy (with replacing) whatever needed from someFile to ss
someFile.close();
someFile.open("t.txt", ios::binary|ios::out|ios::trunc);
someFile << ss.rdbuf();
someFile.close();