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);
}
Related
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);
I'm trying to read a binary file and store it in a buffer. The problem is, that in the binary file are multiple null-terminated characters, but they are not at the end, instead they are before other binary text, so if I store the text after the '\0' it just deletes it in the buffer.
Example:
char * a = "this is a\0 test";
cout << a;
This will just output: this is a
here's my real code:
this function reads one character
bool CStream::Read (int * _OutChar)
{
if (!bInitialized)
return false;
int iReturn = 0;
*_OutChar = fgetc (pFile);
if (*_OutChar == EOF)
return false;
return true;
}
And this is how I use it:
char * SendData = new char[4096 + 1];
for (i = 0; i < 4096; i++)
{
if (Stream.Read (&iChar))
SendData[i] = iChar;
else
break;
}
I just want to mention that there is a standard way to read from a binary file into a buffer.
Using <cstdio>:
char buffer[BUFFERSIZE];
FILE * filp = fopen("filename.bin", "rb");
int bytes_read = fread(buffer, sizeof(char), BUFFERSIZE, filp);
Using <fstream>:
std::ifstream fin("filename.bin", ios::in | ios::binary );
fin.read(buffer, BUFFERSIZE);
What you do with the buffer afterwards is all up to you of course.
Edit: Full example using <cstdio>
#include <cstdio>
const int BUFFERSIZE = 4096;
int main() {
const char * fname = "filename.bin";
FILE* filp = fopen(fname, "rb" );
if (!filp) { printf("Error: could not open file %s\n", fname); return -1; }
char * buffer = new char[BUFFERSIZE];
while ( (int bytes = fread(buffer, sizeof(char), BUFFERSIZE, filp)) > 0 ) {
// Do something with the bytes, first elements of buffer.
// For example, reversing the data and forget about it afterwards!
for (char *beg = buffer, *end=buffer + bytes; beg < end; beg++, end-- ) {
swap(*beg, *end);
}
}
// Done and close.
fclose(filp);
return 0;
}
static std::vector<unsigned char> read_binary_file (const std::string filename)
{
// binary mode is only for switching off newline translation
std::ifstream file(filename, std::ios::binary);
file.unsetf(std::ios::skipws);
std::streampos file_size;
file.seekg(0, std::ios::end);
file_size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<unsigned char> vec;
vec.reserve(file_size);
vec.insert(vec.begin(),
std::istream_iterator<unsigned char>(file),
std::istream_iterator<unsigned char>());
return (vec);
}
and then
auto vec = read_binary_file(filename);
auto src = (char*) new char[vec.size()];
std::copy(vec.begin(), vec.end(), src);
The problem is definitievely the writing of your buffer, because you read a byte at a time.
If you know the length of the data in your buffer, you could force cout to go on:
char *bf = "Hello\0 world";
cout << bf << endl;
cout << string(bf, 12) << endl;
This should give the following output:
Hello
Hello world
However this is a workaround, as cout is foreseent to output printable data. Be aware that the output of non printable chars such as '\0' is system dependent.
Alternative solutions:
But if you manipulate binary data, you should define ad-hoc data structures and printing. Here some hints, with a quick draft for the general principles:
struct Mybuff { // special strtucture to manage buffers of binary data
static const int maxsz = 512;
int size;
char buffer[maxsz];
void set(char *src, int sz) // binary copy of data of a given length
{ size = sz; memcpy(buffer, src, max(sz, maxsz)); }
} ;
Then you could overload the output operator function:
ostream& operator<< (ostream& os, Mybuff &b)
{
for (int i = 0; i < b.size; i++)
os.put(isprint(b.buffer[i]) ? b.buffer[i]:'*'); // non printables replaced with *
return os;
}
ANd you could use it like this:
char *bf = "Hello\0 world";
Mybuff my;
my.set(bf, 13); // physical copy of memory
cout << my << endl; // special output
I believe your problem is not in reading the data, but rather in how you try to print it.
char * a = "this is a\0 test";
cout << a;
This example you show us prints a C-string. Since C-string is a sequence of chars ended by '\0', the printing function stops at the first null char.
This is because you need to know where the string ends either by using special terminating character (like '\0' here) or knowing its length.
So, to print whole data, you must know the length of it and use a loop similar to the one you use for reading it.
Are you on Windows? If so you need to execute _setmode(_fileno(stdout), _O_BINARY);
Include <fcntl.h> and <io.h>
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.
I'm making a enciphering/deciphering program using XTEA algorithm. The encipher/decipher functions work fine, but when I encipher a file and then decipher it, I get some extra characters in the end of the file:
--- Original file ---
QwertY
--- Encrypted file ---
»¦æŸS#±
--- Deciphered from encrypted ---
QwertY ß*tÞÇ
I have no idea why the " ß*tÞÇ" appears in the end.
I will post some of my code, but not all of it since it would be too long. The encipher/decipher function takes 64 bits data and 128 bits key, and encipher/decipher the data to the same block size, which is again 64 bits (similar functions here). It can then be written to a new file.
long data[2]; // 64bits
ZeroMemory(data, sizeof(long)*2);
char password[16];
ZeroMemory(password, sizeof(char)*16);
long *key;
if(argc > 1)
{
string originalpath = argv[1];
string finalpath;
string eextension = "XTEA";
string extension = GetFileExtension(originalpath);
bool encipherfile = 1;
if(extension.compare(eextension) == 0) // If extensions are equal, dont encipher file
{
encipherfile = 0;
finalpath = originalpath;
finalpath.erase(finalpath.length()-5, finalpath.length());
}
ifstream in(originalpath, ios::binary);
ofstream out(finalpath, ios::binary);
cout << "Password:" << endl;
cin.get(password,sizeof(password));
key = reinterpret_cast<long *>(password);
while(!in.eof())
{
ZeroMemory(data, sizeof(long)*2);
in.read(reinterpret_cast<char*>(&data), sizeof(long)*2); // Read 64bits from file
if(encipherfile == 1)
{
encipher(data, key);
out.write(reinterpret_cast<char*>(&data), sizeof(data));
continue;
}
if(encipherfile == 0)
{
decipher(data, key);
out.write(reinterpret_cast<char*>(&data), sizeof(data));
}
}
Check for eof immediately after your read, and if you get eof break out of the loop.
If you may have partial reads (i.e. it is possible to read fewer than all of the requested bytes), then you need also to call gcount to find out how many bytes you actually read, thus:
cin.read( ... )
if( cin.eof() )
{
streamsize bytesRead = cin.gcount();
if( bytesRead > 0 )
// process those bytes
break;
}
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
}