Can somebody tell if this is correct?
I try to read from binary file line by line and store it in a buffer? does the new line that it stores in the buffer delete the previous stored line?
ifs.open(filename, std::ios::binary);
for (std::string line; getline(ifs, line,' '); )
{
ifs.read(reinterpret_cast<char *> (buffer), 3*h*w);
}
For some reason you are mixing getline which is text-based reading, and read(), which is binary reading.
Also, it's completely unclear, what is buffer and what's it size. So, here is a simple example for you to start:
ifs.open(filename, std::ios::binary); // assume, that everything is OK
constexpr size_t bufSize = 256;
char buffer[bufSize];
size_t charsRead{ 0 };
do {
charsRead = ifs.read(buffer, bufSize)
// check if charsRead == 0, if it's ok
// do something with filled buffer.
// Note, that last read will have less than bufSize characters,
// So, query charsRead each time.
} while (charsRead == bufSize);
Related
I am Trying to read 64000 bytes from file in binary mode in buffer at one time till end of the file. My problem is tellg() returns position in hexadecimal value, How do I make it return decimal value?
because my if conditions are not working, it is reading more than 64000 and when I am relocating my pos and size_stream(size_stream = size_stream - 63999;
pos = pos + 63999;), it is pointing to wrong positions each time.
How do I read 64000 bytes from file into buffer in binary mode at once till the end of file?
Any help would be appreciated
std::fstream fin(file, std::ios::in | std::ios::binary | std::ios::ate);
if (fin.good())
{
fin.seekg(0, fin.end);
int size_stream = (unsigned int)fin.tellg(); fin.seekg(0, fin.beg);
int pos = (unsigned int)fin.tellg();
//........................<sending the file in blocks
while (true)
{
if (size_stream > 64000)
{
fin.read(buf, 63999);
buf[64000] = '\0';
CString strText(buf);
SendFileContent(userKey,
(LPCTSTR)strText);
size_stream = size_stream - 63999;
pos = pos + 63999;
fin.seekg(pos, std::ios::beg);
}
else
{
fin.read(buf, size_stream);
buf[size_stream] = '\0';
CString strText(buf);
SendFileContent(userKey,
(LPCTSTR)strText); break;
}
}
My problem is tellg() returns position in hexadecimal value
No, it doesn't. It returns an integer value. You can display the value in hex, but it is not returned in hex.
when I am relocating my pos and size_stream(size_stream = size_stream - 63999; pos = pos + 63999;), it is pointing to wrong positions each time.
You shouldn't be seeking in the first place. After performing a read, leave the file position where it is. The next read will pick up where the previous read left off.
How do I read 64000 bytes from file into buffer in binary mode at once till the end of file?
Do something more like this instead:
std::ifstream fin(file, std::ios::binary);
if (fin)
{
unsigned char buf[64000];
std::streamsize numRead;
do
{
numRead = fin.readsome(buf, 64000);
if ((!fin) || (numRead < 1)) break;
// DO NOT send binary data using `LPTSTR` string conversions.
// Binary data needs to be sent *as-is* instead.
//
SendFileContent(userKey, buf, numRead);
}
while (true);
}
Or this:
std::ifstream fin(file, std::ios::binary);
if (fin)
{
unsigned char buf[64000];
std::streamsize numRead;
do
{
if (!fin.read(buf, 64000))
{
if (!fin.eof()) break;
}
numRead = fin.gcount();
if (numRead < 1) break;
// DO NOT send binary data using `LPTSTR` string conversions.
// Binary data needs to be sent *as-is* instead.
//
SendFileContent(userKey, buf, numRead);
}
while (true);
}
i have been messing around with raw image headers, things like bitmap headers, icon headers etc just to see how one could use it to wrap custom data inside, but i have one problem, if i read from a stream the vector contains just as many bytes as the file stored on disk, but when i write its contents out to file(even without the ppm header) it contains junk characters, its about 150 bytes longer than what the original file was :L this makes me think that the input stream appends junk character.
Here's my code, StreamReadFile and GetFilesize is just some functions that i need because i do alot of reading and writing to file in my project ^^
vector<char> StreamReadFile(LPWSTR path, long FileSize, int pos) {
ifstream InputStream(path, ios::in | ios::binary);
vector<char> buffer(FileSize);
long ticks = 0;
if(pos > 0) {
InputStream.seekg(pos);
}
while(FileSize > ticks) {
buffer[ticks] = InputStream.get();
ticks++;
}
return buffer;
}
long GetFileSize(LPWSTR path) {
ifstream stream(path, ios_base::in | ios_base::binary);
if(stream.is_open()) {
stream.seekg(0, ios_base::end);
return (long) stream.tellg();
}
return -1;
}
int CreatePPM(vector<char> image) {
#pragma pack(push, 1)
PPMFILEHEADER ppm;
ppm.width = image.size() / 2;
ppm.height = image.size() / 2;
ppm.size = image.size();
ppm.data = image.data();
vector<char> input = StreamReadFile(L"MessageBox.exe", GetFileSize(L"MessageBox.exe"), 0);
ofstream filestream("drop.ppm");
filestream.write(input.data(), input.size());
filestream.close();
#pragma pack(pop)
return 0;
}
Any help whatsoever will be greatly appreciated ^^
Best regards Paze.
So, here's my problem: I want to make a program that reads chunks of data from a file. Let's say, 1024 bytes per chunk.
So I read the first 1024 bytes, perform various operations and then open the next 1024 bytes, without reading the old data. The program should keep reading data untile the EOF is reached.
I'm currently using this code:
std::fstream fin("C:\\file.txt");
vector<char> buffer (1024,0); //reads only the first 1024 bytes
fin.read(&buffer[0], buffer.size());
But how can I read the next 1024 bytes? I was thinking by using a for loop, but I don't really know how. I'm totally a noob in C++, so if anyone can help me out, that would be great. Thanks!
You can do this with a loop:
std::ifstream fin("C:\\file.txt", std::ifstream::binary);
std::vector<char> buffer (1024,0); //reads only the first 1024 bytes
while(!fin.eof()) {
fin.read(buffer.data(), buffer.size())
std::streamsize s=fin.gcount();
///do with buffer
}
##EDITED
http://en.cppreference.com/w/cpp/io/basic_istream/read
Accepted answer doesn't work for me - it doesn't read last partial chunk. This does:
void readFile(std::istream &input, UncompressedHandler &handler) {
std::vector<char> buffer (1024,0); //reads only 1024 bytes at a time
while (!input.eof()) {
input.read(buffer.data(), buffer.size());
std::streamsize dataSize = input.gcount();
handler({buffer.begin(), buffer.begin() + dataSize});
}
}
Here UncompressedHandler accepts std::string, so I use constructor from two iterators.
I think you missed up that there is a pointer points to the last place you've visit in the file , so that when you read for the second time you will not start from the first , but from the last point you've visit .
Have a look to this code
std::ifstream fin("C:\\file.txt");
char buffer[1024]; //I prefer array more than vector for such implementation
fin.read(buffer,sizeof(buffer));//first read get the first 1024 byte
fin.read(buffer,sizeof(buffer));//second read get the second 1024 byte
so that how you may think about this concept .
I think that will work
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fstream>
// Buffer size 16 Megabyte (or any number you like)
size_t buffer_size = 1 << 24; // 20 is 1 Megabyte
char* buffer = new char[buffer_size];
std::streampos fsize = 0;
std::ifstream file("c:\\file.bin", std::ios::binary);
fsize = file.tellg();
file.seekg(0, std::ios::end);
fsize = file.tellg() - fsize;
int loops = fsize / buffer_size;
int lastChunk = fsize % buffer_size;
for (int i = 0; i < loops; i++) {
file.read(buffer, buffer_size);
// DO what needs with the buffer
}
if (lastChunk > 0) {
file.read(buffer, lastChunk);
// DO what needs with the buffer
}
delete[] buffer;
Like always, problems with pointers. This time I am trying to read a file (opened in binary mode) and store some portion of it in a std::string object.
Let's see:
FILE* myfile = fopen("myfile.bin", "rb");
if (myfile != NULL) {
short stringlength = 6;
string mystring;
fseek(myfile , 0, SEEK_SET);
fread((char*)mystring.c_str(), sizeof(char), (size_t)stringlength, myfile);
cout << mystring;
fclose(myfile );
}
Is this possible? I don't get any message. I am sure the file is O.K. When I try with char* it does work but I want to store it directly into the string. Thanks for your help!
Set the string to be large enough first to avoid buffer overrun, and access the byte array as &mystring[0] to satisfy const and other requirements of std::string.
FILE* myfile = fopen("myfile.bin", "rb");
if (myfile != NULL) {
short stringlength = 6;
string mystring( stringlength, '\0' );
fseek(myfile , 0, SEEK_SET);
fread(&mystring[0], sizeof(char), (size_t)stringlength, myfile);
cout << mystring;
fclose(myfile );
}
There are many, many issues in this code but that is a minimal adjustment to properly use std::string.
I would recommend this as the best way to do such a thing. Also you should check to make sure that all the bytes were read.
FILE* sFile = fopen(this->file.c_str(), "r");
// if unable to open file
if (sFile == nullptr)
{
return false;
}
// seek to end of file
fseek(sFile, 0, SEEK_END);
// get current file position which is end from seek
size_t size = ftell(sFile);
std::string ss;
// allocate string space and set length
ss.resize(size);
// go back to beginning of file for read
rewind(sFile);
// read 1*size bytes from sfile into ss
fread(&ss[0], 1, size, sFile);
// close the file
fclose(sFile);
string::c_str() returns const char* which you can not modify.
One way to do this would be use a char* first and construct a string from it.
Example
char buffer = malloc(stringlength * sizeof(char));
fread(buffer, sizeof(char), (size_t)stringlength, myfile);
string mystring(buffer);
free(buffer);
But then again, if you want a string, you should perhaps ask yourself Why am I using fopen and fread in the first place??
fstream would be a much much better option.
You can read more about it here
Please check out the following regarding c_str to see some things that are wrong with your program. A few issues include the c_str not being modifiable, but also that it returns a pointer to your string contents, but you never initialized the string.
http://www.cplusplus.com/reference/string/string/c_str/
As for resolving it... you could try reading into a char* and then initializing your string from that.
No it is not. std::string::c_str() method does not return a modifiable character sequence as you can validate from here. A better solution would be using a buffer char array. Here is an example:
FILE* myfile = fopen("myfile.bin", "rb");
if (myfile != NULL) {
char buffer[7]; //Or you can use malloc() / new instead.
short stringlength = 6;
fseek(myfile , 0, SEEK_SET);
fread(buffer, sizeof(char), (size_t)stringlength, myfile);
string mystring(buffer);
cout << mystring;
fclose(myfile );
//use free() or delete if buffer is allocated dynamically
}
I've created RLE encoding function, which encodes sequences like "A1A1B7B7B7B7" to such strings: "#A12#B74".
void encode(const char *input_path, const char *output_path)
{ // Begin of SBDLib::SBIMask::encode
std::fstream input(input_path, std::ios_base::in | std::ios_base::binary);
std::fstream output(output_path, std::ios_base::out | std::ios_base::binary);
int size = 0; // Set size variable
input.seekg(0, std::ios::end); // Move to EOF
size = input.tellg(); // Tell position
input.seekg(0); // Move to the beginning
int i = 1; // Create encoding counter
int counter = 0; // Create color counter
int cbyte1, cbyte2; // Create current color bytes
int pbyte1 = 0x0; int pbyte2 = 0x0; // Create previous color bytes
while (((cbyte1 = input.get()) != EOF && (cbyte2 = input.get()) != EOF)
|| input.tellg() >= size)
{ // Begin of while
// If current bytes are not equal to previous bytes
// or cursor is at the end of the input file, write
// binary data to file; don't do it if previous bytes
// were not set from 0x0 to any other integer.
if (((cbyte1 != pbyte1 || cbyte2 != pbyte2)
|| (input.tellg() == size))
&& (pbyte1 != 0x0 && pbyte2 != 0x0))
{ // Begin of main if
output << SEPARATOR; // Write separator to file
output.write(reinterpret_cast<const char*>(&pbyte1), 1);
output.write(reinterpret_cast<const char*>(&pbyte2), 1);
output << std::hex << counter; // Write separator, bytes and count
counter = 1; // Reset counter
} // End of main if
else counter++; // Increment counter
pbyte1 = cbyte1; pbyte2 = cbyte2; // Set previous bytes
} // End of main while
} // End of encode
However, function is not as fast as I need. This is the second version of function, I've already improved it to make it faster, but it is still too slow. Do you have any ideas how to improve? I'm lack of ideas.
Depending on the size of data you are reading from files it might be a good idea not to read single charcaters but a chunk of data from your input file at once. This might be a lot faster than accessing the input file on the disk for each input character.
Pseudo code example:
char dataArray[100];
while( !EOF )
{
input.get( &dataArray[0], 100 ); // read a block of data not a single charater
process( dataArray ); // process one line
}