How can i access the data from a buffer?
int WINAPI mRecv( SOCKET s, char *buf, int len, int flags ) {
// Code to access the data from buffer
}
You are probably looking for std::istream::read. It is used to extract characters from stream.
And if you want to iterate over the data then you can use the std::istreambuf_iterator
std::string
getBufferContent(const std::string& path)
{
std::ifstream file(path);
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
return content;
}
Related
I wrote this code:
ifstream f("file.txt");
char c;
std::string buffer;
buffer.reserve(1024);
bool flag = true;
while (flag) {
for (int i = 0; i < 1024; ++i) {
if (f.get(c))
buffer += c;
else
flag = false;
}
// do something with buffer
buffer.clear();
}
I need exactly 1 KB string buffer. Is there any better and efficient way to do this? Maybe some fstream or string functions which I don't know?
You don't need the for loop, you can use std::istream::read() instead. And if possible, replace the std::string with char[], eg:
ifstream f("file.txt");
char buffer[1024];
while (f.read(buffer, 1024))
{
// do something with buffer up to f.gcount() chars...
}
If, for some reason, you actually needed a std::string, then you can do this:
ifstream f("file.txt");
std::string buffer(1024);
while (f.read(&buffer[0], 1024)) // or buffer.data() in C++17 and later
{
buffer.resize(f.gcount());
// do something with buffer ...
buffer.resize(1024);
}
I am trying to write a char* to a binary file.
This is what I have now.
void Write(char* fileName, char* pData)
{
ofstream binFile (fileName, ios::out | ios::binary);
if (binFile.open())
{
binFile.write((char*)&pData, sizeof(pData));
binFile.close();
}
}
void Read(char* fileName, char* pData)
{
ifstream binFile(fileName, ios::in | ios::binary);
if(binFile.open())
{
binFile.read(char*)&pData, sizeof(pData));
binFile.close
}
}
int main()
{
char* testData = "ABCdEFG"; // not real data
char* getTestData;
char* file = "C:\\testData.dat";
Write(file, testData);
Read(file, getTestData);
}
Test data will be of unknown length. May not always be the same.
When i run the program once, and write and read. I can get back the test data.
But when i stop the program and run it again, this time without writing. Just reading, i cannot get back the test data.
I don't really understand whats happening here.
Can some one explain it to me?
binFile.write((char*)&pData, sizeof(pData));
is wrong. It just writes the value of the pointer. It does not write the data.
You need to use:
binFile.write(pData, strlen(pData));
However, that won't be adequate to read the data back. To be able to read the data back, you'll need to write the size of the string first.
size_t len = strlen(pData);
binFile.write((char*)&len, sizeof(len));
binFile.write(pData, len);
And when reading the data back, you will need to use:
size_t len = 0;
binFile.read(char*)&len, sizeof(len));
binFile.read(pData, len);
and then, null terminate the string.
pData[len] = '\0';
PS
Make sure getTestData is properly initialized before using it to read the data.
char getTestData[100];
will be adequate for your test case.
Update
You can make your program a bit better by using std::string instead of char*. The size of the saved data can be more easily managed when a std::string is used.
void Write(std::string const& fileName, std::string const& data)
{
std::ofstream binFile(fileName, std::ios::out | std::ios::binary);
if (binFile.is_open())
{
size_t len = data.size();
binFile.write((char*)&len, sizeof(len));
binFile.write((char*)&data[0], len);
// No need. The file will be closed when the function returns.
// binFile.close();
}
}
void Read(std::string const& fileName, std::string& data)
{
std::ifstream binFile(fileName, std::ios::in | std::ios::binary);
if(binFile.is_open())
{
size_t len = 0;
binFile.read((char*)&len, sizeof(len));
data.resize(len);
binFile.read((char*)&data[0], len);
}
}
int main()
{
std::string file = "testData.dat";
std::string testData = "ABCdEFG";
Write(file, testData);
std::string getTestData;
Read(file, getTestData);
std::cout << getTestData << std::endl;
}
When i try to create my shader with CreateVertexShader(), I get COM error 'The paremeter is incorrect.'.
struct ShaderData
{
LPVOID ShaderCode;
size_t ShaderSize;
};
This function works but it leaks. When delete[] buffer is uncommented I get the error.
Shader::ShaderData Shader::LoadShader(const std::string& file)
{
std::ifstream ifs(file, std::ios::in | std::ios::binary);
if (!ifs) return;
ifs.seekg(0, std::ios::end);
size_t size = static_cast<std::size_t>(ifs.tellg());
ifs.seekg(0, std::ios::beg);
char* buffer = new char[size];
ifs.read(buffer, len);
ShaderData data = { buffer, size };
//delete[] buffer;
return data;
}
Another version of the same function but using std::vector, I still get the same error.
Shader::ShaderData Shader::LoadShader(const std::string& file)
{
std::ifstream ifs(file, std::ios::in | std::ios::binary);
if (!ifs) return;
ifs.seekg(0, std::ios::end);
size_t size = static_cast<std::size_t>(ifs.tellg());
ifs.seekg(0, std::ios::beg);
std::vector<char> buffer(size);
ifs.read(buffer.data(), size);
ShaderData data = { static_cast<void*>(buffer.data()), size };
return data;
}
Function creating the shaders. m_vertex_data and m_pixel_data are both member variables of class Shader, and holds the data returned from LoadShader().
void Shader::CreateShaders(ID3D11Device* device)
{
device->CreateVertexShader(m_vertex_data.ShaderCode,
m_vertex_data.ShaderSize,
nullptr,
m_vertex_shader.GetAddressOf()));
device->CreatePixelShader(m_pixel_data.ShaderCode,
m_pixel_data.ShaderSize,
nullptr,
m_pixel_shader.GetAddressOf()));
}
You need to keep the buffer pointed to by ShaderData::ShaderCode; valid until you create a shader. To avoid leaks just replace it with ::std::vector< char > ShaderCode; so the buffer will be kept safe. Actually you don't need ShaderData struct at all, just return a vector containing shader code.
I am trying to write a char* to a binary file.
This is what I have now.
void Write(char* fileName, char* pData)
{
ofstream binFile (fileName, ios::out | ios::binary);
if (binFile.open())
{
binFile.write((char*)&pData, sizeof(pData));
binFile.close();
}
}
void Read(char* fileName, char* pData)
{
ifstream binFile(fileName, ios::in | ios::binary);
if(binFile.open())
{
binFile.read(char*)&pData, sizeof(pData));
binFile.close
}
}
int main()
{
char* testData = "ABCdEFG"; // not real data
char* getTestData;
char* file = "C:\\testData.dat";
Write(file, testData);
Read(file, getTestData);
}
Test data will be of unknown length. May not always be the same.
When i run the program once, and write and read. I can get back the test data.
But when i stop the program and run it again, this time without writing. Just reading, i cannot get back the test data.
I don't really understand whats happening here.
Can some one explain it to me?
binFile.write((char*)&pData, sizeof(pData));
is wrong. It just writes the value of the pointer. It does not write the data.
You need to use:
binFile.write(pData, strlen(pData));
However, that won't be adequate to read the data back. To be able to read the data back, you'll need to write the size of the string first.
size_t len = strlen(pData);
binFile.write((char*)&len, sizeof(len));
binFile.write(pData, len);
And when reading the data back, you will need to use:
size_t len = 0;
binFile.read(char*)&len, sizeof(len));
binFile.read(pData, len);
and then, null terminate the string.
pData[len] = '\0';
PS
Make sure getTestData is properly initialized before using it to read the data.
char getTestData[100];
will be adequate for your test case.
Update
You can make your program a bit better by using std::string instead of char*. The size of the saved data can be more easily managed when a std::string is used.
void Write(std::string const& fileName, std::string const& data)
{
std::ofstream binFile(fileName, std::ios::out | std::ios::binary);
if (binFile.is_open())
{
size_t len = data.size();
binFile.write((char*)&len, sizeof(len));
binFile.write((char*)&data[0], len);
// No need. The file will be closed when the function returns.
// binFile.close();
}
}
void Read(std::string const& fileName, std::string& data)
{
std::ifstream binFile(fileName, std::ios::in | std::ios::binary);
if(binFile.is_open())
{
size_t len = 0;
binFile.read((char*)&len, sizeof(len));
data.resize(len);
binFile.read((char*)&data[0], len);
}
}
int main()
{
std::string file = "testData.dat";
std::string testData = "ABCdEFG";
Write(file, testData);
std::string getTestData;
Read(file, getTestData);
std::cout << getTestData << std::endl;
}
I have to write C++ program that like gzip can
*Take input from file or from char stream like compression below
gzip file
type file | gzip
*Program have file or char stream output like decompression below
gzip -d file.gz
gzip -dc file.gz
I don't know how to take to the task and what techniques have to use and how to create classes buffering input and output. I have classes buffering input and output and read/write data from/to file.
DataBuffer.h (taking uncompressed data from file):
#ifndef DataBuffer_h
#define DataBuffer_h
#include <fstream>
#include <string>
enum DataBufferState
{
DATABUFFER_OK = 0,
DATABUFFER_EOF = 1
};
class DataBuffer
{
std::fstream file;
std::string buffer;
unsigned int maxBufferSize;
public:
DataBuffer(const std::string& filename, unsigned int maxBuffSize);
~DataBuffer();
bool OpenFile(const std::string& filename);
void SetMaxBufferSize(unsigned int maxBuffSize);
DataBufferState FullBufferWithDataOld();
DataBufferState FullBufferWithData();
std::string GetDataBuffer();
};
#endif
DataBuffer.cpp:
#include "DataBuffer.h"
using namespace std;
DataBuffer::DataBuffer(const string& filename, unsigned int maxBuffSize)
{
OpenFile(filename);
SetMaxBufferSize(maxBuffSize);
}
DataBuffer::~DataBuffer()
{
file.close();
}
bool DataBuffer::OpenFile(const string& filename)
{
file.open(filename.c_str(),ios::in);
if(!file.is_open())
return false;
return true;
}
void DataBuffer::SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
DataBufferState DataBuffer::FullBufferWithDataOld()
{
while(true)
{
string line;
streampos pos = file.tellg(); // Zapamietaj polozenie przed pobraniem linii
getline(file,line);
if( buffer.size()+line.size()>maxBufferSize )
{
// Cofnac wskaznik pliku
file.seekg(pos,ios::beg); // Przywroc polozenie sprzed pobrania linii
break;
}
buffer += line + "\n";
if(file.eof())
return DATABUFFER_EOF;
}
return DATABUFFER_OK;
}
DataBufferState DataBuffer::FullBufferWithData()
{
char c;
for(unsigned int i=0;i<maxBufferSize;++i)
{
c = file.get();
if(file.eof()) break;
buffer += c;
}
if(file.eof())
return DATABUFFER_EOF;
return DATABUFFER_OK;
}
string DataBuffer::GetDataBuffer()
{
string buf = buffer;
buffer.clear();
return buf;
}
BufferWriter.h (Save uncompressed data into file):
#ifndef BufferWriter_h
#define BufferWriter_h
#include <string>
#include <fstream>
class BufferWriter
{
std::string filename;
std::fstream file;
public:
BufferWriter(const std::string& filename_);
~BufferWriter();
bool OpenFile(const std::string& filename, bool appending);
void SendBufferToFile(std::string& buffer);
};
#endif
BufferWriter.cpp
#include "BufferWriter.h"
using namespace std;
BufferWriter::BufferWriter(const string& filename_)
{
filename = filename_;
OpenFile(filename.c_str(),false);
file.close();
}
BufferWriter::~BufferWriter()
{
file.close();
}
bool BufferWriter::OpenFile(const string& filename, bool appending)
{
if(appending)
file.open(filename.c_str(),ios::out | ios::app);
else
file.open(filename.c_str(),ios::out);
if(!file.is_open())
return false;
return true;
}
void BufferWriter::SendBufferToFile(string& buffer)
{
OpenFile(filename,true);
file.write(buffer.c_str(),buffer.size());
file.close();
}
Can you give me some hints how to improve code for input and output mechanisms?
Assume that I have class presented below, how to use istream or iterators to fill buffer with data from file or standard input. What classes from std or boost? What parameters? Somelike to support definition of class with this functionality.
[EDIT]:
#ifndef StreamBuffer_h
#define StreamBuffer_h
#include <string>
using namespace std;
enum DataBufferState
{
DATABUFFER_OK = 0,
DATABUFFER_EOF = 1
};
// gzip plik
// type plik | gzip -d
// gzip -d plik.gz
// gzip -dc plik.gz
// Parametr konstruktora to strumien z ktorego chcemy czytac i dlugosc bufora
class StreamBuffer
{
int maxBufferSize;
std::string buffer;
StreamBuffer(int maxBuffSize)
{
SetMaxBufferSize(maxBuffSize);
}
~StreamBuffer()
{
}
void SetMaxBufferSize(unsigned int maxBuffSize)
{
maxBufferSize = maxBuffSize;
}
DataBufferState FullBufferWithData()
{
// What to use what to do in this method to read part of file or standard char input to buffer?
}
std::string GetDataBuffer()
{
return buffer;
}
};
#endif
[EDIT2]:
I want to do the same thing as in this thread: Read from file or stdin, but in C++.
In general you read input from a source and write it to a sink. The simplest case is when you simply write what you read. You, however, want to apply a transformation (or filter) to the data that you read. Seeing as you're after "the c++ way," I'd suggest taking a look at boost::iostreams which abstracts the task in terms of sources/sinks.
Boost defines an abstract source by:
struct Source {
typedef char char_type;
typedef source_tag category;
std::streamsize read(char* s, std::streamsize n)
{
// Read up to n characters from the input
// sequence into the buffer s, returning
// the number of characters read, or -1
// to indicate end-of-sequence.
}
};
And sinks are defined in a similar way (with a write instead of a read, of course). The benefit of this is that the details of the source/sink is irrelevant - you can read/write to file, to a network adapter, or whatever, without any structural changes.
To apply filters I'd again suggest looking at boost::iostreams, although they do abstract a lot which somewhat complicates implementation..