我试图通过套接字在Linux上通过TCP发送C ++中的wav文件,但我不明白如何正确读取wav文件。
我的目标是将客户端上的文件读入char数组,并使用" write()"到服务器,服务器应该再次将数据写入本地wav文件。
我读了这样的.wav文件:
////////////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));
}
在服务器上,这将返回数组" RIFF"长度" 4",所以它是wav文件头部的一部分。
如何正确读取整个.wav文件内容以写入TCP套接字?
感谢。
答案 0 :(得分:2)
buffer
的类型为char*
,因此sizeof(buffer)
是平台上普通数据指针的大小。所以你要在你的套接字上写4或8个字节(假设普通的平台形式)。
您需要将filesize
放入write
来电,而不是sizeof(buffer)
。
(sizeof
是一个编译时构造。它是在编译代码时进行评估的。它不能返回在运行时确定的大小。)
答案 1 :(得分:2)
在行n = write(socket, buffer, sizeof(buffer));
中,最后一个缓冲区的值变为平台上指针的大小。由于只发送了四个字节,我将假设您使用的是32位平台或以32位模式编译应用程序。
替换sizeof(buffer)
只是部分解决方案,因为write()
可能无法一次写入所有数据。您需要检查从write()
返回的值,并记录已写入套接字的字节数。
答案 2 :(得分:2)
这很简单:filesize
是文件的大小(以字节为单位)。但是,sizeof(buffer)
在32位操作系统上只有4。像这样修改你的代码:
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; // !!
}
为了简化另一方的处理,您可能需要先发送filesize
以避免解析RIFF标头以了解要接受的字节数。我还建议分配一个较小的缓冲区并多次读取以发送较大的文件:
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; // !!
}
您可能会注意到使用辅助函数write_all
。这是必需的,因为套接字可能已满,然后write
将不会写入提供给它的所有数据。它看起来像这样:
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;
}
答案 3 :(得分:1)
我使用sndfile来处理wav文件。