Read unknown symbols when read a content of file - c++

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?

Related

How to find string in exe?

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.

_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) C++ FILE

I know there are several posts on this error but they are of specific cases.
I'm making a file split/joiner, which has the following requirement:
-User must enter file name/input path and output folder.
I wrote the split function with the basic part of splitting original file into N part (which user must enters) and everything was fine.
I then made some modifications to the function to meet the "output folder" requirement and then when I ran the program, that error appeared (was successfully built though).
Can someone explain/clarify what do I do wrong in my code? I am still a beginner at handling file/memory leaks so all helps/criticism are appreciated.
char *GetFileName(char *path)
{
char *filename = strrchr(path, '\\');
if (filename == NULL)
filename = path;
else
filename++;
return filename;
}
void split_F(const char* file_name, const char* output_folder, int number_of_part)
{
FILE *fp_read = fopen(file_name, "rb");
//calculate file size
int file_size;
fseek(fp_read, 0L, SEEK_END);
file_size = ftell(fp_read);
rewind(fp_read); //reset file pointer
//calculate number of parts
long size_of_part;
size_of_part = (int)ceil((double)file_size / number_of_part);
cout << "Total files after split: " << number_of_part << endl
<< "...Processing..." << endl;
//extract file name
char *first_part = new char[255];
char *temp = new char[255];
strcpy(temp, file_name);
first_part = GetFileName(temp);
cout << endl << "File name is: " << first_part;
//main process
char* name = new char[255];
strcpy(name, output_folder);
int bytesRemaining = file_size;
//create buffer
char *buffer = new char[size_of_part];
for (int count = 1; count <= number_of_part; count++)
{
sprintf(name, "%s.part_%03d", first_part, count); //attach file name to output directory
FILE *fp_write = fopen(name, "wb");
long partSize;
if (bytesRemaining > size_of_part)
{
partSize = size_of_part;
}
else
{
partSize = bytesRemaining;
}
fread(buffer, partSize, 1, fp_read);
fwrite(buffer, partSize, 1, fp_write);
cout << "> File: " << name << " done babe!" << endl;
fclose(fp_write);
}
fclose(fp_read);
delete[] buffer;
delete[] name;
delete[] temp;
delete[] first_part;
}
First, your code has a lot of issues, all due to using C-style coding instead of using C++. Instead, if you used std::string and C++ streams, a lot of these issues will resolve themselves.
First issue is that you never checked if the file existed:
FILE *fp_read = fopen(file_name, "rb");
If fp_read is NULL, you never checked for it, and your code goes on as if nothing is wrong. This is incorrect.
Then in your code you do this:
FILE *fp_write = fopen(name, "wb");
Again, you go on without checking if fp_write is ok, when it could be NULL.
But let's assume that fp_read and fp_write are not NULL
//extract file name
char *first_part = new char[255];
char *temp = new char[255];
strcpy(temp, file_name);
There are 2 potential problems with the above.
The first problem is that you do no check to ensure that file_name is less than 255 characters. If file_name is larger than expected, you have a memory overwrite at the call to strcpy. Use strncpy or memcpy where you state the number characters to copy over.
The second issue is more subtle, and that is you called new[] twice. What if the second call to new[] throws an exception? How are you going to deallocate the first call to new[]? You can't. In addition, your input file will still be opened due to the exception being thrown.
This is why std::string and ifstream ofstream should be used in these cases. These types automatically release any resources allocated if the function returns for any reason whatsoever. Using C style strings and I/O leaves you vulnerable to leaks.
The same issue here:
//main process
char* name = new char[255];
strcpy(name, output_folder);
int bytesRemaining = file_size;
//create buffer
char *buffer = new char[size_of_part];
All of these calls to new[] can potentially throw, thus leaving this function, and leaving you with memory leaks and open file handles.
The other issue is that you need to ensure that your buffer does not get overrun. This code:
long partSize;
if (bytesRemaining > size_of_part)
{
partSize = size_of_part;
}
else
{
partSize = bytesRemaining;
}
can be shortened to this:
partSize = std::min(bytesRemaining, size_of_part);
This makes it clear what your intentions are.
Another issue is that your bytesRemaining never gets updated during the loop where you're writing your output. You should have
bytesRemaining -= partSize;
within the loop.
Paul McKenzie covered most of this, but there are some other problems with your string handling. The best solution is to use C++ features like he said (std::string, std::ifstream, std::stringstream, std::unique_ptr, std::shared_ptr, etc.), but if you want to do the C way, there are some improvements you can make.
//extract file name
char *first_part = new char[255];
char *temp = new char[255];
strcpy(temp, file_name);
first_part = GetFileName(temp);
cout << endl << "File name is: " << first_part;
First, you allocate a new 255-byte string for first_part, and then 3 lines later you throw it away and replace it with the result of GetFileName(temp). temp itself is a copy of file_name but it's not clear why since you never change either of them. Maybe you got a warning passing file_name to GetFileName()? Try changing the function signature to add const:
const char *GetFileName(const char *path)
Then change the block of code above into:
//extract file name
first_part = GetFileName(temp);
cout << endl << "File name is: " << first_part;
Now you have 2 fewer heap allocations to deal with.
Now if you look at this code:
char* name = new char[255];
strcpy(name, output_folder);
/* ... */
for (int count = 1; count <= number_of_part; count++)
{
sprintf(name, "%s.part_%03d", first_part, count);
There are two problems here. The first is that name has a constant size and it isn't very big, so there's no need to allocate it on the heap with new. Just declare it as char name[255]; and the memory will be handled for you.
The second problem is that you copy output_folder into name, and then a few lines later you overwrite it. So, just remove that strcpy.
The third problem is that first_part could be 255 bytes long, and name is only 255 bytes long, so your sprintf could overflow. I would fix this by making name at least 15 bytes longer, and using snprintf just in case.
Result:
char name[300];
/* ... */
for (int count = 1; count <= number_of_part; count++)
{
snprintf(name, sizeof(name), "%s.part_%03d", first_part, count);

Using fstream and fstream.eof. Working with files

I'm trying to make a programm, which will read the file, change specified word to symbols '#' and write back to same file. But I have problems with that.
1st question.
It seems like I need to store file in buffer before writing it to the file. How should I do it?
2nd question:
I cant understand why loop in this code never ends? It's about 200 words in that file, but I always get memory exception and i gets 10075.
int main(int argc, char* argv[]){
char** temp = new char*[10000];
int i = 0;
fstream fTemp("D:\doc.txt", ios_base::in);
while (!fTemp.eof()){
temp[i] = new char[50];
fTemp >> temp[i];
temp[i][1] = '#';
cout << temp[i] << endl;
i++;
}
fTemp.open("D:\doc.txt", ios_base::trunc);
for (int i = 0; i < sizeof(*temp); i++){
fTemp << temp[i];
}
_getch();
}
First, you should use getline as your usage of eof is incorrect (eof bit is set only after failed read).
Next, store the strings in a std::vector<string>. This will allow you to not care about memory management (current one is leaking) and provide a more flexible solution.
std::string buffer;
std::vector<string> data;
while(std::getline(fTemp,buffer)) {
data.push_back(buffer);
}
The problem you probably have, is the incorrect eof() call, buy you should check you cout output to determine the problem with this code.
to store the data of file in a buffer, you can get the size of file and use the function read to get all file data. see this code:
// Load file in a buffer
ifstream fl(FileName);
fl.seekg(0, ios::end);
size_t len = fl.tellg();
char* fdata = new char[len];
fl.seekg(0, ios::beg);
fl.read(fdata, len);
fl.close();
in your case the same fstream that you used to open are being used to write without close the file before reopen.
Your loop never ends because it is a pointer, and it size isn't managed, the better way is get the size of file while it is open, in this case the size of file is the "size_t len".
to rewrite your code you can create another stream, see this code:
// Write File
ofstream flOut(FileName, ios_base::trunc);
flOut.write(fdata, len);
flOut.close();
between these two codes above, you can change the data of fdata, but what exactly you wanna make? is replace some word to symbol '#'? which word?

Opening files over 5 mb and storing them in an array

I want to put each byte in a char array and rewrite the text file removing the first 100,000 characters.
int fs=0;
ifstream nm,nm1;
nm1.open("C:\\Dev-Cpp\\DCS\\Decom\\a.txt");
if(nm1.is_open())
{
nm1.seekg(0, ios::end );
fs = nm1.tellg();
}
nm1.close();
char ss[500000];
nm.open("C:\\Dev-Cpp\\DCS\\Decom\\a.txt");
nm.read(ss,fs-1);
nm.close();
ofstream om;
om.open("C:\\Dev-Cpp\\DCS\\Decom\\a.txt");
for(int i=100000;i<fs-1;i++){
om >> ss[i];
}
om.close();
Problem is i can't set the character array to a 5 million size. I tried using vector also
vector <char> ss (5000000);
int w=0;
ifstream in2("C:\\Dev-Cpp\\DCS\\Decom\\a.txt", ios::binary);
unsigned char c2;
while( in2.read((char *)&c2, 1) )
{
in2 >> ss[w];
w++;
}
Over here the size of w is almost half that of fs and a lot of characters are missing.
How to do it ?
In most implementations, char ss[5000000] tries allocating on the stack, and the size of the stack is limited as compared to the overall memory size. You can often allocate larger arrays on the heap than on the stack, like this:
char *ss = new char [5000000];
// Use ss as usual
delete[] ss; // Do not forget to delete
Note that if the file size fs is larger than 5000000, you will write past the end of the buffer. You should limit the amount of data that you read:
nm.read(ss,min(5000000,fs-1));
This part is not correct
while( in2.read((char *)&c2, 1) )
{
in2 >> ss[w];
w++;
}
bacause you first try to read one character into c2 and, if that succeeds, read another character into ss[w].
I'm not at all surprised if you lose about half the characters here!
The best way to solve your problem is to use the facilities of the standard library. That way, you also don't have to care about buffer overflows.
The following code is untested.
std::fstream file("C:\\Dev-Cpp\\DCS\\Decom\\a.txt", std::ios_base::in);
if (!file)
{
std::cerr << "could not open file C:\\Dev-Cpp\\DCS\\Decom\\a.txt for reading\n";
exit(1);
}
std::vector<char> ss; // do *not* give a size here
ss.reserve(5000000); // *expected* size
// if the file is too large, the capacity will automatically be extended
std::copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(),
std::back_inserter(ss));
file.close();
file.open("C:\\Dev-Cpp\\DCS\\Decom\\a.txt", std::ios_base::out | std::ios_base::trunc);
if (!file)
{
std::cerr << "could not open C:\\Dev-Cpp\\DCS\\Decom\\a.txt for writing\n";
exit(1);
}
if (ss.size() > 100000) // only if the file actually contained more than 100000 characters
std::copy(ss.begin()+100000, ss.end(), std::ostreambuf_iterator<char>(file));
file.close();

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.