How to find string in exe? - c++

is
find
function can't work with exe? i try to find wstring in an exe. it always not match. but if i create a txt and copy binary inside exe to txt and it can find it.
std::wifstream file(L"D:/file.exe", std::ios::binary);
if (file.is_open())
{
file.seekg(0, file.end);
std::streamoff length = file.tellg();
file.seekg(0, file.beg);
wchar_t *buffer = new wchar_t[length];
file.read(buffer, length);
std::wstring sFile;
sFile = buffer;
size_t index = sFile.find(L"Something");
if (index != std::string::npos) std::cout << "It's found";
file.close();
delete[] buffer;
}
else
{
std::cout << "It's not open";
}

The executable probably has a number of 0 bytes (i.e. 0x00) early on in the file. When you do sFile = buffer; it assumes that buffer is a C-style string that ends in a 0 byte. So sFile will only contain the bytes up to that point.
To fix it you should put the whole buffer into the string:
std::wstring sFile(buffer, length); // Directly using the constructor, or
sFile.assign(buffer, length); // after construction

Just change
std::wstring sFile;
sFile = buffer;
to
std::wstring sFile(buffer, buffer+length);
When you assigning char-buffer to wstring object, the length of the string is determined by the first null character. So, the first 0x00 byte containing in your file denotes the end of string.

Related

Using newline character in WriteConsoleOutputCharacter C++

I am trying to write a string directly to the console buffer in C++ using WriteConsoleOutputCharacter. I read the contents of a file which contains multiple \n characters but when I write to the console buffer it doesn't write the rest of the file on the next line instead it writes ??. In notepad it says my file encoding is utf-8. I wondered if this had anything to do with it but when I print the file contents using cout the line breaks where ever it encounters \n.
std::ifstream file("debug.txt");
static HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD ir = 0;
if (file.is_open()) {
file.seekg(0, file.end);
int len = file.tellg();
std::cout << len;
file.seekg(0, file.beg);
char* string = (char*)calloc(len+1, sizeof(char));
string[len] = '\0';
file.read(string, len);
file.close();
COORD coord = { 0, 0 };
WriteConsoleOutputCharacterA(
console,
string,
len,
coord,
&ir
);
free(string);
This is how I read from the file and write to the console buffer. Any thoughts?

ifstream::read keeps returning incorrect value

I am currently working my way through teaching myself how to work with files in c++, and I am having a good bit of difficulty extracting binary information from files.
My code:
std::string targetFile = "simplehashingfile.txt";
const char* filename = targetFile.c_str();
std::ifstream file;
file.open( filename, std::ios::binary | std::ios::in );
file.seekg(0, std::ios::end); // go to end of file
std::streamsize size = file.tellg(); // get size of file
std::vector<char> buffer(size); // create vector of file size bytes
file.read(buffer.data(), size); // read file into buffer vector
int totalread = file.gcount();
// Check that data was read
std::cout<<"total read: " << totalread << std::endl;
// check buffer:
std::cout<<"from buffer vector: "<<std::endl;
for (int i=0; i<size; i++){
std::cout << buffer[i] << std::endl;
}
std::cout<<"\n\n";
The "simplehashingfile.txt" file only contains 50 bytes of normal text. The size is correctly determined to be 50 bytes, but gcount returns 0 chars read, and the buffer output is (understandably from the gcount) a 50 line list of nothing.
For the life of me I cannot figure out where I went wrong! I made this test code earlier:
// Writing binary to file
std::ofstream ofile;
ofile.open("testbinary", std::ios::out | std::ios::binary);
uint32_t bytes4 = 0x7FFFFFFF; // max 32-bit value
uint32_t bytes8 = 0x12345678; // some 32-bit value
ofile.write( (char*)&bytes4 , 4 );
ofile.write( (char*)&bytes8, 4 );
ofile.close();
// Reading from file
std::ifstream ifile;
ifile.open("testbinary", std::ios::out | std::ios::binary);
uint32_t reading; // variable to read data
uint32_t reading2;
ifile.read( (char*)&reading, 4 );
ifile.read( (char*)&reading2, 4 );
std::cout << "The file contains: " << std::hex << reading << std::endl;
std::cout<<"next 4 bytes: "<< std::hex << reading2 << std::endl;
And that test code wrote and read perfectly. Any idea what I am doing wrong? Thank you to anyone who can point me in the right direction!
You never reset the file back to the beginning when you read from it
std::streamsize size = file.tellg(); //<- goes to the end of the file
std::vector<char> buffer(size); // create vector of file size bytes
file.read(buffer.data(), size); //<- now we read from the end of the file which will read nothing
int totalread = file.gcount();
You need to call seekg() again and reset the file pointer back to the beginning. To do that use
fille.seekg(0, std::ios::beg);
before
file.read(buffer.data(), size);
It would be worth to return to the begin of the file, before trying to read:
file.seekg(0, std::ios::beg)
I think the problem is that you do a seek to the end to get the file size, but don't seek back to the beginning before trying to read the file.

Read unknown symbols when read a content of file

As in the title, when read a content of file i find it reads unknown symbols with the content.
The code:
char *buff = NULL;
size_t size = 0;
ifstream file("c:\\file.txt", ios::out);
if(!file){
cout << "File does not open." << endl;
}
file.seekg(0, file.end);
size = file.tellg();
file.seekg(0, file.beg);
buff = new char[size];
while(!file.eof()){
file.read(buff, size);
}
cout << buff << endl;
delete[] buff;
The file content:
Hello world!.
Thank you for help.
The result:
As you seen in the previous image, there are many unknowns symbols.
Why these symbols appear, what's wrong in my code ?
Your char array is not null terminated, either create the array with space for one extra null character (and set it to '\0')
buff = new char[size + 1];
buff[size] = '\0';
// Or simply
buff = new char[size + 1]{};
or even better avoid using raw pointers wherever possible, especially for character arrays used as strings.
while(!file.eof()) is an antipattern, don't use it except in very specific cases.
std::ifstream file("file.txt");
std::string buff{ // Use regular brackets if not C++11
std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()
};
You can only use operator<<(const char *) for C-style strings. You can't use it for arbitrary chunks of bytes. How would it know where to stop?

How to write a non-English string to a file and read from that file with C++?

I want to write a std::wstring onto a file and need to read that content as std:wstring. This is happening as expected when the string as L"<Any English letter>". But the problem is happening when we have character like Bengali, Kannada, Japanese etc, any kind of non English letter. Tried various options like:
Converting the std::wstring to std::string and write onto the file and reading time read as std::string and convert as std::wstring
Writing is happening (I could see from edito) but reading time getting wrong character
Writing std::wstring onto wofstream, this is also not helping for
native language character letters like std::wstring data = L"হ্যালো ওয়ার্ল্ড";
Platform is mac and Linux, Language is C++
Code:
bool
write_file(
const char* path,
const std::wstring data
) {
bool status = false;
try {
std::wofstream file(path, std::ios::out|std::ios::trunc|std::ios::binary);
if (file.is_open()) {
//std::string data_str = convert_wstring_to_string(data);
file.write(data.c_str(), (std::streamsize)data.size());
file.close();
status = true;
}
} catch (...) {
std::cout<<"exception !"<<std::endl;
}
return status;
}
// Read Method
std::wstring
read_file(
const char* filename
) {
std::wifstream fhandle(filename, std::ios::in | std::ios::binary);
if (fhandle) {
std::wstring contents;
fhandle.seekg(0, std::ios::end);
contents.resize((int)fhandle.tellg());
fhandle.seekg(0, std::ios::beg);
fhandle.read(&contents[0], contents.size());
fhandle.close();
return(contents);
}
else {
return L"";
}
}
// Main
int main()
{
const char* file_path_1 = "./file_content_1.txt";
const char* file_path_2 = "./file_content_2.txt";
//std::wstring data = L"Text message to write onto the file\n"; // This is happening as expected
std::wstring data = L"হ্যালো ওয়ার্ল্ড";
// Not happening as expected.
// Lets write some data
write_file(file_path_1, data);
// Lets read the file
std::wstring out = read_file(file_path_1);
std::wcout<<L"File Content: "<<out<<std::endl;
// Let write that same data onto the different file
write_file(file_path_2, out);
return 0;
}
How a wchar_t is output depends on the locale. The default
locale ("C") generally doesn't accept anything but ASCII
(Unicode code points 0x20...0x7E, plus a few control
characters.)
Any time a program handles text, the very first statement in
main should be:
std::locale::global( std::locale( "" ) );
If the program uses any of the standard stream objects, the code
should also imbue them with the global locale, before any
input or output.
To read and write unicode files (assuming you want to write unicode characters) you can try fopen_s
FILE *file;
if((fopen_s(&file, file_path, "w,ccs=UNICODE" )) == NULL)
{
fputws(your_wstring().c_str(), file);
}
One possible problem may be when you read the string back, because you set the length of the string to the number of bytes in the file and not the number of characters. This means that you attempt to read past the end of the file, and also that the string will contain trash at the end.
If you're dealing with text files, why not simply use the normal output and input operators << and >> or other textual functions like std::getline?
Later edit: this is for Windows (since no tag was present at the time of the answer)
You need to set the stream to a locale that supports those characters . Try something like this (for UTF8/UTF16):
std::wofstream myFile("out.txt"); // writing to this file
myFile.imbue(std::locale(myFile.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
And when you read from that file you have to do the same thing:
std::wifstream myFile2("out.txt"); // reading from this file
myFile2.imbue(std::locale(myFile2.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
Do not use wstring or wchar_t. On non-Windows platforms wchar_t is pretty much worthless these days.
Instead you should use UTF-8.
bool
write_file(
const char* path,
const std::string data
) {
try {
std::ofstream file(path, std::ios::out | std::ios::trunc | std::ios::binary);
file.exceptions(true);
file << data;
return true;
} catch (...) {
std::cout << "exception!\n";
return false;
}
}
// Read Method
std::string
read_file(
const char* filename
) {
std::ifstream fhandle(filename, std::ios::in | std::ios::binary);
if (fhandle) {
std::string contents;
fhandle.seekg(0, std::ios::end);
contents.resize(fhandle.tellg());
fhandle.seekg(0, std::ios::beg);
fhandle.read(&contents[0], contents.size());
return contents;
} else {
return "";
}
}
int main()
{
const char* file_path_1 = "./file_content_1.txt";
const char* file_path_2 = "./file_content_2.txt";
std::string data = "হ্যালো ওয়ার্ল্ড"; // linux and os x compilers use UTF-8 as the default execution encoding.
write_file(file_path_1, data);
std::string out = read_file(file_path_1);
std::wcout << "File Content: " << out << '\n';
write_file(file_path_2, out);
}

C++ Ifstream reads too much?

I'm trying to read a file and output the contents. Everything works fine, I can see the contents but it seems to add about 14 empty bytes at the end. Does anyone know whats wrong with this code?
int length;
char * html;
ifstream is;
is.open ("index.html");
is.seekg (0, ios::end);
length = is.tellg();
is.seekg (0, ios::beg);
html = new char [length];
is.read(html, length);
is.close();
cout << html;
delete[] html;
You didn't put a null terminator on your char array. It's not ifstream reading too much, cout just doesn't know when to stop printing without the null terminator.
If you want to read an entire file, this is much easier:
std::ostringstream oss;
ifstream fin("index.html");
oss << fin.rdbuf();
std::string html = oss.str();
std::cout << html;
That is because html is not null-terminated string, and std::cout keeps printing character until it finds \0, or it may crash your program
Do this:
html = new char [length +1 ];
is.read(html, length);
html[length] = '\0'; // put null at the end
is.close();
cout << html;
Or, you can do this:
cout.write(html, length);
cout.write will stop printing exactly after length number of chars.