I have to write some data to a text file, and at the end of each output I have to append a NULL terminating character '\0'. Currently this is what I have come up so far. It works well for some inputs, however for some it sometimes write the whole text file with garbage value. I there a better way to do this?? In my program I have to write some data, store its location on file and use that for some operations. the next write operation starts at address = address + 500;
long int address = get_address();
void write_to_file()
{
fstream pFILE ("my file.txt");
char * buffer = new char [500];
cin.getline(buffer,500);
pFILE.seekp(address);
pFILE << buffer;
pFILE.seekp(address + strlen(buffer));
pFILE << '\0';
address += 500;
}
To write a '\0' to file:
fstream output_file("output_file.txt", ios::binary);
output_file.put('\0');
The ios::binary prevents the compiler or OS from translating the '\0'.
Related
I have a char array[] and is like following:
// MessageBox
char xcode[] = "\x31\xc9\x64\x8b\x41\x30\x8b\x40\xc\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x1\xda\x8b\x52\x78\x1\xda\x8b\x72\x20\x1\xde\x31\xc9\x41\xad\x1\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x4\x72\x6f\x63\x41\x75\xeb\x81\x78\x8\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x1\xde\x66\x8b\xc\x4e\x49\x8b\x72\x1c\x1\xde\x8b\x14\x8e\x1\xda\x31\xc9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd2\x83\xc4\xc\x59\x50\x51\x66\xb9\x6c\x6c\x51\x68\x33\x32\x2e\x64\x68\x75\x73\x65\x72\x54\xff\xd0\x83\xc4\x10\x8b\x54\x24\x4\xb9\x6f\x78\x41\x0\x51\x68\x61\x67\x65\x42\x68\x4d\x65\x73\x73\x54\x50\xff\xd2\x83\xc4\x10\x68\x61\x62\x63\x64\x83\x6c\x24\x3\x64\x89\xe6\x31\xc9\x51\x56\x56\x51\xff\xd0";
Then i had inserted all this content of variable above into a file (file with UTF-8 format and content without the "") and tried load this way:
ifstream infile;
infile.open("shellcode.bin", std::ios::in | std::ios::binary);
infile.seekg(0, std::ios::end);
size_t file_size_in_byte = infile.tellg();
char* xcode = (char*)malloc(sizeof(char) * file_size_in_byte);
infile.seekg(0, std::ios::beg);
infile.read(xcode, file_size_in_byte);
printf("%s\n", xcode); // << prints content of xcode after load from file
if (infile.eof()) {
size_t bytes_really_read = infile.gcount();
}
else if (infile.fail()) {
}
infile.close();
I'm seeing some strange characters in end of text see:
What is need to fix it?
The issue is that the printf format specifier "%s" requires that the string is null-terminated. In your case, the null-terminator just happens to be after those characters you're seeing, but nothing guarantees where the null is unless you put one there.
Since you're using C++, one way to print the characters is to use the write() function available for streams:
#include <iostream>
//...
std::cout.write(xcode, file_size_in_bytes);
The overall point is this -- if you have a character array that is not null-terminated and contains data, you must either:
Put the null in the right place before using the array in functions that look for the null-terminator or
Use functions that state how many characters to process from the character array.
The answer above uses item 2.
I serialize the file via the code beneath, and send it over winsocks, this works fine with textfiles, but when I tried to send a jpg, the string contains \0 as some of the character elements, so the sockets only send part of the string, thinking \0 is the end, i was considering replacing \0 with something else, but say i replace it with 'xx', then replace it back on the other end, what if the file had natural occurrences of 'xx' that get lost? Sure I could make a large, unlikely sequence, but that bloats the file.
Any help appreciated.
char* read_file(string path, int& len)
{
std::ifstream infile(path);
infile.seekg(0, infile.end);
size_t length = infile.tellg();
infile.seekg(0, infile.beg);
len = length;
char* buffer = new char[len]();
infile.read(buffer, length);
return buffer;
}
string load_to_buffer(string file)
{
char* img;
int ln;
img = read_file(file, ln);
string s = "";
for (int i = 1; i <= ln; i++){
char c = *(img + i);
s += c;
}
return s;
}
Probably somewhere in your code (that isn't seen in the code you have posted) you use strlen() or std::string::length() to send the data, and/or you use std::string::c_str() to get the buffer. This results in truncated data because these functions stop at \0.
std::string is not good to handle binary data. Use std::vector<char> instead, and remove the new[] stuff.
I am writing a program which reads input from a text file and converts it to hexadecimal for later processing.
ifstream fin("input.txt"); //open file with ifstream
if(fin.is_open()){ //check if file is open
for(int i = 0; i<length; i++){ //int length for how many characters I need
fin.get(buffer[i]); //write into char array buffer[256]
}
}
else{
cout<<"Can't open file";
exit(0);
}
fin.close();
So everything is fine, it opens up nicely and gets exactly as many characters as I need from there, later I use a function to turn that into a hexadecimal string:
std::string string_to_hex(const std::string input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
which also works fine, it gives me the correct hexadecimal value for the characters that I get.
Now here is the problem: my file contains null characters (hexadecimal "00" characters aka '\0') which I need to read into my program and do a proper conversion so every null character in my array after conversion should look like "00". Every time I
try to convert null characters in my array they change into spaces (hexadecimal "20"), which ruins my data for processing later. Changing "20" into "00" is also not an option since the file contains real spaces that also need to be properly processed.
This is my first time working with null characters and I am absolutely confused on how to properly process them. All I know is that null characters are used at the end of a string or an array so when I print them out the program would know when to stop.
I do not know how I should do it properly. I tried opening the file differently using fopen, I tried copying my input.txt into an array differently. Maybe it copies it properly but the hex conversion doesn't work. Maybe I shouldn't send it as a string for conversion. I don't know. I also noticed that when I tried to copy paste a sample from the file to another file, all the null characters have been replaced by spaces, maybe it has something to do with this?
Just this:
int size = getFileSize(path); //Listed below
ifstream fs(path, ios::in);
ofstream os(path2, ios::out);
//Check - both streams are valid
char buff[CHUNK_SIZE]; //512
while (size > CHUNK_SIZE)
{
fs >> buff;
os << buff;
size -= CHUNK_SIZE;
}
char* dataLast = new char[size];
fs>>dataLast;
os<<dataLast;
fs.close();
os.close();
//Found on SO, works fine
int getFileSize(string path)
{
FILE *pFile = NULL;
if (fopen_s( &pFile, path.c_str(), "rb" ))
{
return 0;
}
fseek( pFile, 0, SEEK_END );
int Size = ftell( pFile );
fclose( pFile );
return Size;
}
File at path2 is corrupted and less then 1 Kb. (initial file is 30Kb);
I don't need advices how to copy file, I am curios what is wrong about this example.
First an important warning: Never (as in really never) use the formatted input operator for char* without setting the width()! You open yourself up to a buffer overrun. This is basically the C++ version of writing gets() which was bad enough to be removed (not just deprecated) from the C standard! If you insist in using formatted input with char* (normally you are much better off using std::string), set the width, e.g.:
char buffer[512];
in >> std::setw(sizeof(buffer) >> buffer;
OK, with this out of the way: it seems you actually want to change two important things:
You probably don't want to use formatted input, i.e., operator>>(): the formatted input operators start off with skipping whitespace. When reading into char* it also stops when reaching a whitespace (or when the width() is non-zero when having read a much characters and still space to store a terminating zero; note that the set width() will be reset to 0 after each of these reads). That is you probably want to use unformatted input, e.g., in.read(buffer, sizeof(buffer)) which sets in.gcount() to the number of characters actually read which may be less then size parameter, e.g., at the end of the stream.
You probably should open the file in std::ios_base::binary mode. Although it doesn't matter on some systems (e.g., POSIX systems) on some systems reading in text mode merges a line end sequence, e.g. \r\n on Windows, into the line end character \n. Likewise, when writing a \n in text mode, it will be replaced by a line end sequence on some system, i.e., you probably also want to open the output stream in text mode.
Th input and output operators, when used with strings (like buff is from the libraries point of view), reads space-delimited words, only.
If you want to read chunks, then use std::istream::read, and use std::istream::gcount to get the number of bytes actually read. Then write with std::ostream::write.
And if the data in the file is binary, you should use the binary open mode.
I have a program that I need to read binary text into. I read the binary text via a redirection:
readData will be an executable made by my Makefile.
Example: readData < binaryText.txt
What I want to do is read the binary text, and store each character in the binary text file as a character inside a char array. The binary text is made up of 32 This is my attempt at doing so...
unsigned char * buffer;
char d;
cin.seekg(0, ios::end);
int length = cin.tellg();
cin.seekg(0, ios::beg);
buffer = new unsigned char [length];
while(cin.get(d))
{
cin.read((char*)&buffer, length);
cout << buffer[(int)d] << endl;
}
However, I keep getting a segmentation fault on this. Might anyone have any ideas on how to read binary text into a char array? Thanks!
I'm more a C programmer rather than a C++, but I think that you should have started your while loop
while(cin.get(&d)){
The easiest would be like this:
std::istringstream iss;
iss << std::cin.rdbuf();
// now use iss.str()
Or, all in one line:
std::string data(static_cast<std::istringstream&>(std::istringstream() << std::cin.rdbuf()).str());
Something like this should do the trick.
You retrieve the filename from the arguments and then read the whole file in one shot.
const char *filename = argv[0];
vector<char> buffer;
// open the stream
std::ifstream is(filename);
// determine the file length
is.seekg(0, ios_base::end);
std::size_t size = is.tellg();
is.seekg(0, std::ios_base::beg);
// make sure we have enough memory space
buffer.reserve(size);
buffer.resize(size, 0);
// load the data
is.read((char *) &buffer[0], size);
// close the file
is.close();
You then just need to iterate over the vector to read characters.
The reason why you are getting segmentation fault is because you are trying to access an array variable using a character value.
Problem:
buffer[(int)d] //d is a ASCII character value, and if the value exceeds the array's range, there comes the segfault.
If what you want is an character array, you already have that from cin.read()
Solution:
cin.read(reinterpret_cast<char*>(buffer), length);
If you want to print out, just use printf
printf("%s", buffer);
I used reinterpret_cast because it thought it is safe to convert to signed character pointer since most characters that are used would range from 0 ~ 127. You should know that character values from 128 to 255 would be converted wrongly.