Copying wav files c++ - c++

My program (see below) creates a wav file with the header and so on. I can open it but it does not copy all of the Data chunk. The header is OK: I can open the file with WMP and I can hear some noises but as for Data it does not actually copy all the text. I opened both wav files with Wordpad and the data only collects the first 3 lines of chars then its all spaces (so the Data size is good).
fstream ifs(FileInputPath->c_str(), ios_base::in);
cout<< "PATH :" << FileInputPath->c_str()<<endl;
ofstream outfile("C:/Users/miguel/Desktop/proj/Automatic_Visual_Speech_v0.9_beta/exemplo.wav", ofstream::out);
if (ifs.is_open() && outfile.is_open())
{
char First_Chunk_ID[5]=""; //RIFF
ifs.read(First_Chunk_ID,4);
outfile.write(First_Chunk_ID,4);
long File_Size; // FileSize
ifs.read( reinterpret_cast<char*>(&File_Size), sizeof(long) );
outfile.write(reinterpret_cast<char*>(&File_Size),sizeof(long));
char Form_Type_ID[5] =""; //Formato
ifs.read(Form_Type_ID,4);
outfile.write(Form_Type_ID,4);
char Second_Chunk_ID[5] = ""; //2ºPedaco
ifs.read(Second_Chunk_ID,4);
outfile.write(Second_Chunk_ID,4);
/*char * charArray_Wave_Format_Size = new char;
ifs.read(charArray_Wave_Format_Size, sizeof(long));*/
long Wave_Format_Size; //Tamanho do 2º Pedaço
ifs.read( reinterpret_cast<char*>(&Wave_Format_Size), sizeof(long) );
outfile.write(reinterpret_cast<char*>(&Wave_Format_Size), sizeof(long));
char Wave_Format_Info[3] = ""; //Tipo de formato!
ifs.read(Wave_Format_Info, 2);
outfile.write(Wave_Format_Info,2);
short NumChannels; //Canais
ifs.read(reinterpret_cast<char*>(&NumChannels),2);
outfile.write(reinterpret_cast<char*>(&NumChannels),2);
long SampleRate;
ifs.read(reinterpret_cast<char*>(&SampleRate),4);
outfile.write(reinterpret_cast<char*>(&SampleRate),4);
long ByteRate;
ifs.read(reinterpret_cast<char*>(&ByteRate),4);
outfile.write(reinterpret_cast<char*>(&ByteRate),4);
short BlockAlign;
ifs.read(reinterpret_cast<char*>(&BlockAlign),2);
outfile.write(reinterpret_cast<char*>(&BlockAlign),2);
short BitsPerSample;
ifs.read(reinterpret_cast<char*>(&BitsPerSample),2);
outfile.write(reinterpret_cast<char*>(&BitsPerSample),2);
char Third_Chunk_ID[5] = "";
ifs.read(Third_Chunk_ID, 4);
outfile.write(Third_Chunk_ID,4);
long charArray_Data_Size;
ifs.read(reinterpret_cast<char*>(&charArray_Data_Size), sizeof(long));
outfile.write(reinterpret_cast<char*>(&charArray_Data_Size),sizeof(long));
char Data[81600]="";// if you want to read 10000 chars, make a buffer of 10000 chars
ifs.read(Data,charArray_Data_Size+1); // use read(), not get(). Everything in the file is binary
outfile.write(Data,charArray_Data_Size+1);
outfile.close();
}

You don't show how you open the output file so I use a psychic guess: You opened your file as text not binary.
http://en.cppreference.com/w/cpp/io/ios_base/openmode
http://en.cppreference.com/w/cpp/io/basic_ofstream/basic_ofstream

Related

C++ fread() reports back right size read, but buffer is missing data on Windows

Scenario: I have a file that is 8,203,685 bytes long in binary, and I am using fread() to read in the file.
Problem: Hexdumping the data after the fread() on both Linux and Windows yields different results. Both hexdump files are the same size, but on Linux it matches the original input file that went in, whereas on Windows starting at byte 8,200,193 the rest of the hexdump contains 0's.
Code:
int main(void)
{
FILE * fp = fopen("input.exe", "rb");
unsigned char * data = NULL;
long size = 0;
if (fp)
{
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
data = (unsigned char *)malloc(size);
size_t read_bytes = fread(data, 1, size, fp);
// print out read_bytes, value is equal to size
// Hex dump using ofstream. Hexdump file is different here on Windows vs
// on Linux. Last ~3000 bytes are all 0's on Windows.
std::ofstream out("hexdump.bin", std::ios::binary | std::ios::trunc);
out.write(reinterpret_cast<char *>(data), size);
out.close();
FILE * out_file = fopen("hexdump_with_FILE.bin", "wb");
fwrite(data, 1, size, out_file);
fflush(out_file);
fclose(out_file);
}
if (fp) fclose(fp);
if (data) free(data);
return 0;
}
Has anyone seen this behavior before, or have an idea of what might be causing the behavior that I am seeing?
P.S. Everything works as expected when using ifstream and its read function
Thanks!

C++ bitmap editing

I am trying to open a bitmap file, edit it, and then save the edited version as a new file. This is eventually to mess with using steganography. I am trying to save the bitmap information now but the saved file will not open. No errors in compilation or run time. It opens fine and the rest of the functions work.
void cBitmap::SaveBitmap(char * filename)
{
// attempt to open the file specified
ofstream fout;
// attempt to open the file using binary access
fout.open(filename, ios::binary);
unsigned int number_of_bytes(m_info.biWidth * m_info.biHeight * 4);
BYTE red(0), green(0), blue(0);
if (fout.is_open())
{
// same as before, only outputting now
fout.write((char *)(&m_header), sizeof(BITMAPFILEHEADER));
fout.write((char *)(&m_info), sizeof(BITMAPINFOHEADER));
// read off the color data in the bass ackwards MS way
for (unsigned int index(0); index < number_of_bytes; index += 4)
{
red = m_rgba_data[index];
green = m_rgba_data[index + 1];
blue = m_rgba_data[index + 2];
fout.write((const char *)(&blue), sizeof(blue));
fout.write((const char *)(&green), sizeof(green));
fout.write((const char *)(&red), sizeof(red));
}
}
else
{
// post file not found message
cout <<filename << " not found";
}
// close the file
fout.close();
}
You're missing the padding bytes after each RGB row. The rows have to be a multiple of 4 bytes each.
Also, are you supposed to be writing a 24 or 32-bit bmp file? If you're writing 24-bit, you're just missing padding. If you're writing 32-bit, then you're missing each extra byte (alpha). Not enough information to fix your code sample short of writing a complete bmp writer that would support all possible options.

How do I Write a .wav file on C++ using the socket layer in Linux?

I am trying to send wav files in C++ via TCP on Linux over a socket but I don't understand how a wav file can be read correctly.
My goal is to read the file on the client into a char array, send it with "write()" to the server, and the server should write the data into a local wav file again.
I read the .wav file like this:
////////////define socket - left out for simplicity
ifstream file ("audio.wav", ios::in|ios::binary|ios::ate); //open .wav file
char * buffer; //declare data buffer, should contain .wav data to write to socket
streampos filesize; //size of file
int n; //number of written bytes
//if file opened correctly, read content and write to socket
if (file.is_open()){
filesize = file.tellg();
buffer = new char [filesize];
file.seekg (0, ios::beg);
file.read (buffer, filesize);
file.close();
n = write(socket, buffer, sizeof(buffer));
}
On the server, this returns the array "RIFF" of length "4", so its part of the header of the wav file.
How can I read the whole .wav file content correctly for writing to the TCP socket?
Thanks.
That is simple: filesize is size of the file in bytes. However, sizeof(buffer) is only 4 on a 32-bit OS. Modify your code like this:
if(file.is_open()) {
filesize = file.tellg();
buffer = new char [filesize];
file.seekg (0, ios::beg);
file.read (buffer, filesize);
file.close();
n = write_all(socket, buffer, filesize); // use filesize here
delete[] buffer; // !!
}
To simplify processing on the other side, you may want to send filesize first to avoid parsing of the RIFF header to know how many bytes to accept. I would also suggest allocating a smaller buffer and reading several times to send the larger files over:
if(file.is_open()) {
filesize = file.tellg();
file.seekg(0, ios::beg);
uint32_t remains = filesize;
write(socket, &remains, sizeof(uint32_t));
// write 4B with size of the file (optional)
buffer = new char[(filesize > 4096)? 4096 : filesize];
// only up to 4k buffer to avoid running out of memory
n = 0;
while(remains > 0) {
int chunk = (remains > 4096)? 4096 : remains;
// decide how much to read in at one time (not more than size of the buffer)
file.read(buffer, chunk);
n += write_all(socket, buffer, chunk);
// read a chunk and write it to the socket
remains -= chunk;
// update number of bytes that remains to be transferred
}
// send the file several times
file.close();
delete[] buffer; // !!
}
You may notice the use of a helper function write_all. That is required, because the socket might get full and then write will not write all the data given to it. It could look like this:
size_t write_all(int socket, const char *buffer, size_t size)
{
size_t n = 0;
while(size > 0) {
size_t written = write(socket, buffer, size);
if(written == -1)
return written; // handle errors
n += written;
size -= written;
}
return n;
}
buffer is of type char*, so sizeof(buffer) is the size of an ordinary data pointer on your platform. So you're writing 4 or 8 bytes (assuming ordinary plateform) to your socket.
You need to put filesize in the write call instead of sizeof(buffer).
(sizeof is a compile-time construct. It's evaluated when your code is compiled. It can't return a size that's determined at runtime.)
In the line n = write(socket, buffer, sizeof(buffer)); the value of the last buffer becomes the size of a pointer on your platform. Since only four bytes are sent, I will assume that you are either on a 32-bit platform or compiling the application in 32-bit mode.
Replacing sizeof(buffer) will only be a partial solution since write() may not write all the data at once. You will need to check the value returned from write() and keep record of how many bytes have been written to the socket.
I used sndfile for handling wav files.

fwrite doesn't seem to copy the whole file (just the start)

I'm trying to make a exe program that can read any file to binary and later use this binary to make the exact same file.
So I figured out that I can use fopen(content,"rb") to read a file as binary,
and using fwrite I can write block of data into stream. But the problem is when I fwrite it doesn't seems copy everything.
For example the text I opened contains 31231232131 in it. When I write it into another file it only copies 3123 (first 4 bytes).
I can see that it's a very simple thing that I'm missing but I don't know what.
#include <stdio.h>
#include <iostream>
using namespace std;
typedef unsigned char BYTE;
long getFileSize(FILE *file)
{
long lCurPos, lEndPos;
lCurPos = ftell(file);
fseek(file, 0, 2);
lEndPos = ftell(file);
fseek(file, lCurPos, 0);
return lEndPos;
}
int main()
{
//const char *filePath = "C:\\Documents and Settings\\Digital10\\MyDocuments\\Downloads\\123123.txt";
const char *filePath = "C:\\Program Files\\NPKI\\yessign\\User\\008104920100809181000405,OU=HNB,OU=personal4IB,O=yessign,C=kr\\SignCert.der";
BYTE *fileBuf;
FILE *file = NULL;
if ((file = fopen(filePath, "rb")) == NULL)
cout << "Could not open specified file" << endl;
else
cout << "File opened successfully" << endl;
long fileSize = getFileSize(file);
fileBuf = new BYTE[fileSize];
fread(fileBuf, fileSize, 1, file);
FILE* fi = fopen("C:\\Documents and Settings\\Digital10\\My Documents\\Downloads\\gcc.txt","wb");
fwrite(fileBuf,sizeof(fileBuf),1,fi);
cin.get();
delete[]fileBuf;
fclose(file);
fclose(fi);
return 0;
}
fwrite(fileBuf,fileSize,1,fi);
You did read fileSize bytes, but are writing sizeof(...) bytes, that is size of pointer, returned by new.
A C++ way to do it:
#include <fstream>
int main()
{
std::ifstream in("Source.txt");
std::ofstream out("Destination.txt");
out << in.rdbuf();
}
You have swapped the arguments of fread and fwrite. Element size precedes the number of elements. Should be like so:
fread(fileBuf, 1, fileSize, file);
And
fwrite(fileBuf, 1, fileSize, fi);
Also address my comment from above:
Enclose the else clause in { and }. Indentation does not determine blocks in c++. Otherwise your code will crash if you fail to open the file.
EDIT: and the another problem - you have been writing sizeof(fileBuf) bytes which is constant. Instead you should write the exact same number of bytes as you've read. Having in mind the rest of your code you could simply replace sizeof(fileBuf) with fileSize as I've done above.
fileBuf = new BYTE[fileSize];
fread(fileBuf, fileSize, 1, file);
FILE* fi = fopen("C:\\Documents and Settings\\[...]\gcc.txt","wb");
fwrite(fileBuf,sizeof(fileBuf),1,fi);
fileBuf is a pointer to BYTE. You declared it yourself, look: BYTE *fileBuf. And so sizeof(filebuf) is sizeof(BYTE *).
Perhaps you wanted:
fwrite(fileBuf, fileSize, 1, fi);
which closely mirrors the earlier fread call.
I strongly recommend that you capture the return values of I/O functions and check them.

read binary bytes from a jpg file

I need to read bytes from a jpg file in c++ so write this codes:
ifstream in("1.jpg"ios::binary);
while(!in.eof()){
char ch = in.get();
}
as you know a jpg file consist of 256 difference chars that we can save it's repeat in a a arr.but the problem is that this code that i wrote read chars in the form of unicode so it consist of 9256 difference char.how can i read from 1.jpg that it wasn't unicode?
The get function reads unformatted data from the file, it just casts the char it read as an int. Are you seeing data read from the file as different to the actual data in the file? If you are there could be a problem elsewhere in the code, and you should provide more.
Alternatively you could read chunks of unformatted data using read.
int main()
{
std::ifstream in("1.jpg", std::ios::binary);
char buffer[1024];
while (in)
{
in.read(buffer, sizeof(buffer));
if (in.gcount() > 0)
{
// read in.gcount() chars from the file
// process them here.
}
}
}