Reading short from file - c++

I'm trying to read a short from a binary file, but I end up with a lot of 0's
This is the write function
void AudioBuffer::WriteToFile(const string& strFilename)
{
fstream fout(strFilename.c_str(), ios::out|ios::binary);
short sample;
for (VECTOR_SHORT_ITER iter = m_vectorSamples.begin(); iter != m_vectorSamples.end(); iter++)
{
sample = (short) *iter;
fout.write((char *) &sample, sizeof(short));
}
fout.close();
}
And this is what I've got for the reading function, I'm aware of the possible overflow with atoi
void AudioBuffer::FileToBuffer(const string& strFilename)
{
fstream fin(strFilename.c_str(), ios::in|ios::binary);
short iSample;
char *temp = new char[sizeof(short)];
cout<<"Samples Output"<<endl;
while(!fin.eof())
{
fin.read(temp,sizeof(short));
iSample = atoi(temp);
cout<<iSample< " ";
m_vectorSamples.push_back(iSample);
*temp = NULL;
}
fin.close();
}
Also, clearing the char pointer by doing the *temp = NULL isn't the best thing right?
Thanks

Since you're just writing raw bits into the file, you want to read the same way, something on this order:
void AudioBuffer::FileToBuffer(const string& strFilename)
{
ifstream fin(strFilename.c_str(), ios::in|ios::binary);
short iSample;
cout<<"Samples Output"<<endl;
while(fin.read((char *)&iSample,sizeof(short)))
{
cout<<iSample<< " ";
m_vectorSamples.push_back(iSample);
}
}

Related

How to read string from a binary file in C++?

I have a function two functions, writing and reading from the binary file in C++.
void save_ascII(string ascII_text, string filename)
{
ofstream fout;
fout.open(filename,ofstream::binary);
size_t input_size = ascII_text.size();
if (fout.is_open())
{
fout.write(reinterpret_cast<char*>(&input_size), sizeof(input_size));
fout.write(reinterpret_cast<char*>(&input_size), input_size);
fout.close();
}
}
void read_ascII(string filename)
{
string read_input;
ifstream fin(filename,fstream::binary);
size_t read_size;
if (fin.is_open())
{
fin.read(reinterpret_cast<char*>(&read_size), sizeof(read_size));
read_input.resize(read_size);
fin.read(&read_input[0], read_size);
fin.close();
}
}
The problem is that when it reads from the binary, it just dummy data on the memory.
When it reads from the binary file, it shows:
►╠╠╠╠╠╠╠╠▄²A
Any suggestion really appreciates it.
In your code,
size_t input_size = ascII_text.size();
if (fout.is_open())
{
fout.write(reinterpret_cast<char*>(&input_size), sizeof(input_size));
fout.write(reinterpret_cast<char*>(&input_size), input_size); //<--bug
fout.close();
}
instead of the line marked with bug<--, you need
fout.write(ascII_text.data(), input_size);

how to read line by line string in a text file?

this code will only read and calculate the first input in the input.txt file and ignore the rest of the inputs in the input file.I have been trying to solve it so that it can read all the rest of the inputs and calculate them.
this is my code i think there is something wrong with it.
i have tried several looping methods
int main()
{
string inputLine;
ifstream file ("input.txt");// input file to be read
ofstream file1;
file1.open("output.txt");
freopen("output.txt", "w", stdout);// store all the output to this file
while (std::getline (file, inputLine)) // read the strings in the input file
{
if( strncmp( "----", inputLine.c_str(), 4 ) == 0 )
continue;
//calculating binary and hexadecimal values
char *opr = "^+-/%*=,()";
std::string::iterator end_pos = std::remove(inputLine.begin(),
inputLine.end(), ' ');
inputLine.erase(end_pos, inputLine.end());
string str=inputLine;
string str2="";
int length=str.length();
char t[length];
str.copy(t, length);
t[length] = '\0';
char* tok;
char *cop=new char [length];
str.copy(cop,length);
char *w = strtok_fixed( t, opr );
while (w!=NULL)
{
string w2=w;
std::stringstream tr;
tr << w2;
w2.clear();
tr >> w2;
int x=w2.length();
int y=x-3;
string check= w2.substr(0,3);
string check1=w2.substr(0,x);
if(check.find("0x") != std::string::npos)
{
unsigned int x= strtol(w2.c_str(), NULL, 0);
std::ostringstream s;
s << x;
const std::string ii(s.str());
str2=str2+ ii;
}
else if (check1.find("b")!=std::string::npos)
{
w2.pop_back();
long bin=std::strtol(w2.c_str(),0,2);
std::ostringstream s2;
s2<<bin;
const std::string t2(s2.str());
//inputLine.replace(inputLine.find(w2),(w2.length()+1),t2);
str2=str2+t2;
}
else
{
str2=str2+w2;
}
char a =cop[w-t+strlen(w)];
string s1="";
s1=s1+a;
std::stringstream tr1;
tr1 << s1;
s1.clear();
tr1 >> s1;
str2=str2+s1;
w = strtok_fixed (NULL, opr);
}
//str2 should be taken to the parser for final evaluations
Parser p(str2);
double value = p.Evaluate ();
std::cout<<"----------------------"<<endl;
std::cout << "Result = " << value << std::endl;
std::cout<<"----------------------"<<endl;
return 0;
}
}
The problem is at the end
return 0;
}
}
should be
}
return 0;
}
You are returning from inside your while loop instead of after your while loop finishes.
You should spend the time to indent your code correctly. It will help you spot this kind of error. You should also learn to break up your code into smaller functions. Again this will help you understand your own code a bit better.

C++ read binary file char by char

I have an assignment of saving some objects data in a specific order of its data members, I'll try to simplfy . Consider this Base class constructor from a binary file. (Please note that it was not my choice to use char *) .
Base(ifstream & in_file) {
int n;
in_file.read((char *)&n, sizeof(n));
m_var = new char[n + 1];
in_file.read(m_var, n);
m_var[n] = '\0';
in_file.read((char *)&m_intvar, sizeof(m_intvar));
}
It has to initialize m_var (char *) and another integer variable. This code works, though it requiers to save the length of the char * for me to allocate the memory.
The problem starts here. I was instructed not to save the size of the string, but to only enter a \n after each value i write to the file. So I need some how to read the file, and get the string until the \n character.
I was thinking about reading char by char, but couldn't find a way to do it, I assume there is an istream function that offers that. Some similar function to >> of a text file would also be good I assume.
After consulting cppreference.com I end up as follows:
#include <fstream>
#include <iostream>
#include <cstring>
class Base
{
public:
Base(std::istream & in_file) { // NOTE: changed to istream to allow reading from any stream not just files
in_file.read((char *)&n, sizeof(n));
char buffer[1024];
in_file.get(buffer, sizeof(buffer), '\n');
size_t gcount = in_file.gcount();
if (in_file.get() != '\n')
{
throw std::runtime_error("binary string to long"); // you may want to implement a loop here using peek() to check for newline
}
m_var = new char[gcount];
std::copy(buffer, buffer + gcount, m_var);
}
Base(int num, const char* strg)
: n(num)
, m_var(strdup(strg))
{
}
bool operator == (const Base& rhs)
{
return n == rhs.n && strcpy(m_var, rhs.m_var);
}
void write(std::ostream& out)
{
out.write((char*)&n, sizeof(n));
out.write(m_var, strlen(m_var));
out.write("\n", 1);
}
int n;
char* m_var = nullptr;
~Base()
{
delete m_var;
}
};
int main(int, char**)
{
Base b1(10, "Hello Word!");
{
std::ofstream out("testfile.bin");
b1.write(out);
}
std::ifstream in("testfile.bin");
Base b2(in);
if (b1 == b2)
{
std::cout << "read ok!" << std::endl;
}
else
{
std::cout << "read failed!" << std::endl;
}
return 0;
}
4 years later but I was having a similar problem and found this post.
You can read char by char as you mention, with a loop.
int i;
for(i=0;;i++){
cout<<i;
in_file.read(&buffer[i],sizeof(char));
if buffer[i]=='\n') break;
}
The only problem with the code I came up is it saves the '\n'. But you can and should replace it to the NULL char '\0' after having found the new line '\n'.
(buffer[i]=='\0')
Please correct me if I am mistaken.

c++ writing and reading objects to binary files

I'm trying to read an array object (Array is a class I've made using read and write functions to read and write from binary files. So far the write functions works but it won't read from the file properly for some reason. This is the write function :
void writeToBinFile(const char* path) const
{
ofstream ofs(path, ios_base::out | ios_base::app | ios_base::binary);
if (ofs.is_open())
{
ostringstream oss;
for (unsigned int i = 0; i < m_size; i++)
{
oss << ' ';
oss << m_data[i];
}
ofs.write(oss.str().c_str(), oss.str().size());
}
}
This is the read function :
void readFromBinFile(const char* path)
{
ifstream ifs(path, ios_base::in | ios_base::binary || ios_base::ate);
if (ifs.is_open())
{
stringstream ss;
int charCount = 0, spaceCount = 0;
ifs.unget();
while (spaceCount != m_size)
{
charCount++;
if (ifs.peek() == ' ')
{
spaceCount++;
}
ifs.unget();
}
ifs.get();
char* ch = new char[sizeof(char) * charCount];
ifs.read(ch, sizeof(char) * charCount);
ss << ch;
delete[] ch;
for (unsigned int i = 0; i < m_size; i++)
{
ss >> m_data[i];
m_elementCount++;
}
}
}
those are the class fields :
T* m_data;
unsigned int m_size;
unsigned int m_elementCount;
I'm using the following code to write and then read (1 execution for reading another for writing):
Array<int> arr3(5);
//arr3[0] = 38;
//arr3[1] = 22;
//arr3[2] = 55;
//arr3[3] = 7;
//arr3[4] = 94;
//arr3.writeToBinFile("binfile.bin");
arr3.readFromBinFile("binfile.bin");
for (unsigned int i = 0; i < arr3.elementCount(); i++)
{
cout << "arr3[" << i << "] = " << arr3[i] << endl;
}
The problem is now at the readFromBinFile function, it get stuck in an infinite loop and peek() returns -1 for some reason and I can't figure why.
Also note I'm writing to the binary file using spaces to make a barrier between each element so I would know to differentiate between objects in the array and also a space at the start of the writing to make a barrier between previous stored binary data in the file to the array binary data.
The major problem, in my mind, is that you write fixed-size binary data in variable-size textual form. It could be so much simpler if you just stick to pure binary form.
Instead of writing to a string stream and then writing that output to the actual file, just write the binary data directly to the file:
ofs.write(reinterpret_cast<char*>(m_data), sizeof(m_data[0]) * m_size);
Then do something similar when reading the data.
For this to work, you of course need to save the number of entries in the array/vector first before writing the actual data.
So the actual write function could be as simple as
void writeToBinFile(const char* path) const
{
ofstream ofs(path, ios_base::out | ios_base::binary);
if (ofs)
{
ofs.write(reinterpret_cast<const char*>(&m_size), sizeof(m_size));
ofs.write(reinterpret_cast<const char*>(&m_data[0]), sizeof(m_data[0]) * m_size);
}
}
And the read function
void readFromBinFile(const char* path)
{
ifstream ifs(path, ios_base::in | ios_base::binary);
if (ifs)
{
// Read the size
ifs.read(reinterpret_cast<char*>(&m_size), sizeof(m_size));
// Read all the data
ifs.read(reinterpret_cast<char*>(&m_data[0]), sizeof(m_data[0]) * m_size);
}
}
Depending on how you define m_data you might need to allocate memory for it before reading the actual data.
Oh, and if you want to append data at the end of the array (but why would you, in the current code you show, you rewrite the whole array anyway) you write the size at the beginning, seek to the end, and then write the new data.

read in txt file in C++

I have a .txt parameter file like this:
#Stage
filename = "a.txt";
...
#Stage
filename = "b.txt";
...
Basically I want to read one stage each time I access the parameter file.
I planed to use getline in C++ with delimiter "#Stage" to do this. Or there is a better way to solve this? Any sample codes will be helpful.
*struct content{
DATA data;
content* next;
};
struct List{
content * head;
};
static List * list;
char buf[100];
FILE * f = fopen(filename);
while(NULL != fgets(buf,f))
{
char str[100] ={0};
sccanf(buf,"%s",str);
if(strcmp("#Stage",str) == 0)
{
// read content and add to list
cnntent * p = new content();
list->add();
}
else
{
//update content in last node
list->last().data =
}
}*
Maybe I should express more clear. Anyway, I manage like this:
ifstream file1;
file1.open(parfile, ios::binary);
if (!file1) {
cout<<"Error opening file"<<parfile<<"for read"<<endl;
exit(1);
}
std::istreambuf_iterator<char> eos;
std::string s(std::istreambuf_iterator<char>(file1), eos);
unsigned int block_begin = 0;
unsigned int block_end = string::npos;
for (unsigned int i=0; i<stage; i++) {
if(s.find("#STAGE", block_begin)!=string::npos) {
block_begin = s.find("#STAGE", block_begin);
}
}
if(s.find("#STAGE", block_begin)!=string::npos) {
block_end = s.find("#STAGE", block_begin);
}
string block = s.substr(block_begin, block_end);
stringstream ss(block);
....
I'd read line by line, ignoring the lines, starting with # (or the lines, with content #Stage, depending on the format/goal) (as there's no getline version, taking std::string as delimiter).