This is driving me insane. I'm a beginner/intermediate C++er and I need to do something that seems simple. I have a string with A LOT of hex characters in it. They were inputted from a txt file. The string looks like this
07FF3901FF030302FF3f0007FF3901FF030302FF3f00.... etc for a while
How can I easily write these hex values into a .dat file? Everytime I try, it writes it as text, not hex values. I already tried writing a for loop to insert "\x" every byte but it still is written as text.
Any help would be appreciated :)
Note: Obviously, if I can even do this, then I don't know that much about c++ so try not to use things WAY over my head. Or at least explain it a bit. Pweeeez:)
You should be clear about the difference of char(ascii) and hex values.
Assume in x.txt:
ascii reads as: "FE"
In binary ,x.txt is "0x4645(0100 0110 0100 0101)".In ascii, 'F'=0x46,'E'=0x45.
Notice everything is computer is stored in binary code.
You want to get x.dat:
the binary code of x.dat is "0xFE(1111 1110)"
So, you should tranfer the ascii text into the proper hex values then write it into the x.dat.
The sample code:
#include<iostream>
#include<cstdio>
using namespace std;
char s[]="FE";
char r;
int cal(char c)// cal the coresponding value in hex of ascii char c
{
if (c<='9'&&c>='0') return c-'0';
if (c<='f'&&c>='a') return c-'a'+10;
if (c<='F'&&c>='A') return c-'A'+10;
}
void print2(char c)//print the binary code of char c
{
for(int i=7;i>=0;i--)
if ((1<<i)&c) cout << 1;
else cout << 0;
}
int main()
{
freopen("x.dat","w",stdout);// every thing you output to stdout will be outout to x.dat.
r=cal(s[0])*16+cal(s[1]);
//print2(r);the binary code of r is "1111 1110"
cout << r;//Then you can open the x.dat with any hex editor, you can see it is "0xFE" in binary
freopen("CON","w",stdout); // back to normal
cout << 1;// you can see '1' in the stdout.
}
Related
In my code bellow CODE 1 reading HEX from a file and storing in in string array won't convert it to ASCII when printed out.
#include <iostream>
#include <sstream>
#include <fstream>
int main(int argc, char** argv)
{
// CODE 1
std::ifstream input("C:\\test.txt"); // The test.txt contains \x48\x83\xEC\x28\x48\x83
std::stringstream sstr;
input >> sstr.rdbuf();
std::string test = sstr.str();
std::cout << "\nString from file: " << test;
//char* lol = new char[test.size()];
//memcpy(lol, test.data(), test.size());
////////////////////////////////////////////////////////
// CODE 2
std::string test_2 = "\x48\x83\xEC\x28\x48\x83";
std::cout << "\n\nHardcoded string: " << test_2 << "\n";
// Prints as ASCII "H(H" , which I want my CODE 1 to do.
}
In my CODE 2 sample, same HEX is used and it prints it as ASCII. Why is it not the same for CODE 1?
Okay, it looks like there is some confusion. First, I have to ask if you're SURE you know what is in your file.
That is, does it contain, oh, it looks like about 20 characters:
\
x
4
8
et cetera?
Or does it contain a hex 48 (one byte), a hex 83 (one byte), for a total of 5-ish characters?
I bet it's the first. I bet your file is about 20 characters long and literally contains the string that's getting printed.
And if so, then the code is doing what you expect. It's reading a line of text and writing it back out. If you want it to actually interpret it like the compiler does, then you're going to have to do the steps yourself.
Now, if it actually contains the hex characters (but I bet it doesn't), then that's a little different problem, and we'll have to look at that. But I think you just have a string of characters that includes \x in it. And reading / writing that isn't going to automatically do some magic for you.
When you read from file, the backslash characters are not escaped. Your test string from file is literally an array of chars: {'\\', 'x', '4', '8', ... }
Whereas your hardcoded literal string, "\x48\x83\xEC\x28\x48\x83"; is fully hex escaped by the compiler.
If you really want to store your data as a text file as a series of "backslash x NN" sequences, you'll need to convert after you read from file. Here's a hacked up loop that would do it for you.
std::string test = sstr.str();
char temp[3] = {};
size_t t = 0;
std::string corrected;
for (char c : test)
{
if (isxdigit(c))
{
temp[t] = c;
t++;
if (t == 2)
{
t = 0;
unsigned char uc = (unsigned char)strtoul(tmp, nullptr, 16);
corrected += (char)uc;
}
}
}
You can split the returned string in \x then make casting from string to int,
finally casting to char.
this resource will be helpful
strtok And convert
I know this title might sound confusing. I have a simple question which I haven't been able to solve yet.
Lets imagine I have a file, opening it with an Hex Editor shows it has two characters inside, say 0x1B and 0x00 (obviously unprintable). I'd like to take that as 1B00 in HEX, which is 6912 in DEC, as opposed to directly converting the characters which would be wrong and is what all other questions I saw asked. Well, thats the task I want to do here. Seems simple, but everything I've tried just does it wrong! Even though I am obviously opening the file in binary mode.
I have only managed to read the characters individually, and mess around a bit, but never do what I actually want, which is as simple as taking those 2 hex characters, interpreting them as an Hex Number, and then convert it to Decimal.
Sorry for any unclear idea, Im not a native speaker. Any help will be appreciated, Im sure you'll think this was quite a noobish question :P
EDIT: Sorry, apparently I didn't explain myself properly. I know this might seem abstract, but it is a really concrete little thing which I have struggled to get solved, yet I haven't been able. Maybe I can ask it another way:
How can I scan a character in binary mode, lets say 0x1B, and convert that to actual 1B characters. Just that.
Sounds like you want to read the file as raw data, and then display it on the screen in decimal? Super easy!
int main() {
std::ifstream myfile("filename.data", std::ofstream::binary);
uint16_t number;
char* buffer = (char*)(&number);
while(myfile.read(buffer, sizeof(number))) {
std::cout << number << ' ';
}
}
The reason it's so easy is that there's no hexidecimal involved. The file is saved as a series of bytes, each byte holds one of 256 values. They aren't hex, they're just a series of values. If you read two bytes into the uint16_t, that is the easiest way to interpret two bytes as a single unsigned 2 byte value. And streaming out a uint16_t will, by default, display that value in decimal. There's no hexidecimal involved. The hexidecimal you saw in the hex editor was because a hex editor interprets the bytes as hex values.
If all you want to do is print a number in hexadecimal form, use std::hex
int i = 0x1B;
std::cout << std::hex << i << std::endl;
std::ifstream infile("test.bin", std::ofstream::binary);
while (true)
{
char c1 = ifs.get();
if (!infile.good())
{
break;
}
char c2 = ifs.get();
if (!infile.good())
{
break;
}
int num = (int)c1 |((int)c2 << 8);
// if you need the oppisite order then
// int num = (int)c2 &((int)c1 << 8);
cout << num;
}
I am Programming on Mac OS X 10.6 with XCode. Im trying to make a Programm that "decrypts" a Pokemon GBA game so that you can read the dialogs of the game with any Text Editor.
I already got a programm finished witch does that, so I can read all Text Data.
My problem is, that I need to change the clear Text back to Hex after editing it, but I have no Idea what im making wrong.
string PathDE;
string PathGBA;
string Zeichen;
int kontrolle = 0;
int current = 0;
char buffer1[3] = "00";
char buffer2[3] = "a1";
...
schreiben.open(PathGBA.c_str(), ios::out | ios::binary); //writes out the edited hex
lesen.open(PathDE.c_str(), ios::in); //reads in the plain text
while(current <= kontrolle){
lesen.read(reinterpret_cast<char*>(&a), 1);
converter << a;
converter >> Zeichen;
if(Zeichen == "_"){
schreiben.write(buffer1,3);
}
else if(Zeichen == "0"){
schreiben.write(buffer2,3);
}
...
I Tryed that, but when I open the result in a Hex Editor, the ASCII code is only a8.a8.a8.a8... and so on till eof, and the Hex code is 61 38 00 ... till eof.
I also tryed other methods, but all with the same result, I cant write the decoded GBA as Hex so I can play it with edited Text.
You will want to convert your string into a byte[] with the correct encoding.
Here is the Gen3 text table for Pokemon
http://datacrystal.romhacking.net/wiki/Pok%C3%A9mon_FireRed_-_TBL
Once converted correctly you will simply just insert it into your rom.
Sorry if this doesnt help much but I only have made c# Pokemon tools, not c++.
And btw pokemon doesnt use a ascii hex encryption it uses a form of utf8.
I want to convert a series of 32-bit integer values into a sequence of printable 8-bit character values. Mapping the 32-bit integers to printable 8-bit character values should result in a clear ASCII art image.
I can convert Integer to ASCII:
#include <iostream>
using namespace std;
int main() {
char ascii;
int numeric;
cout << "Enter Number ";
cin >> numeric;
cout << "The ascii value of " << numeric << " is " << (char) numeric<<"\n\n"<<endl;
return 0;
}
Also I need to open the text file that my numbers are saved into:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("1.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else
cout << "Unable to open file";
return 0;
}
but my problem is , I can not open this " Text " file and print the ASCII on the screen and also print a copy of that in a " Output.txt "
Inside of my Text file is just :
757935403 544999979 175906848 538976380
757795452 170601773 170601727
That after converting to ASCII needs to look like this :
represents the ASCII art picture
+---+
| |
| |
+---+
and have this also in my output.txt.
Please advise if you know how can I write this program.
First of all, you cannot convert a 32 bit integer to 8 bit ascii without losing information. As far as I guess, you should extract 4 ascii chars from a 32 bit integer.
If your input file is non-binary (which means integer values are human-readable/seperated by some delimeter), first thing you should do is create another file/stream and write these values to the new file/stream but now in binary mode (In this mode, there will be no delimiter and resulting file/stream will not be human readable).
Now read chars one by one(open file with binary mode) from this new file/stream, and write it to your final output file using non-binary mode.
IF YOU WANT TO DO IT WITHOUT SEVERAL FILE INOUTS,
Read all your integer values in an array, then point the starting memory location with a char pointer, then write one by one the contents of this char array.
int* myIntArray; //keep the size of it somewhere
char* myCharArray =(char*)myIntArray; // size for myCharArray is 4 times of the myIntArray
Having converted those numbers into hex, you get this
2d2d2d2b 207c0a2b 0a7c2020 2020207C
- - - + | lf+ lf| |
etc etc
so basically for some reason the input file contains the characters to output stored as integers. Which is completely endian unsafe.
Your least worst bet it to read in each integer, cast it to an array of chars and output those 4 chars.
If you're using unix, I'd suggest using 'tee' to send your output to 2 files if you can, otherwise output once to stdout, then output again to whatever file handle you've opened for Output.txt.
Edit: I'm trying to convert a text file into bytes. I'm not sure if the code is turning it into bytes or not. Here is the link to the header so you can see the as_bytes function.
link
#include "std_lib_facilities.h"
int main()
{
cout << "Enter input file name.\n";
string file;
cin >> file;
ifstream in(file.c_str(), ios::binary);
int i;
vector<int> bin;
while(in.read(as_bytes(i), sizeof(int)))
bin.push_back(i);
ofstream out(file.c_str(), ios::out);
for(int i = 0; i < bin.size(); ++i)
out << bin[i];
keep_window_open();
}
Note that now the out stream just outputs the contents of the vector. It doesn't use the write function or the binary mode. This converts the file to a large line of numbers - is this what I'm looking for?
Here is an example of the second code's file conversion:
that guy likes to eat lots of pie (not sure if this was exact text)
turns to
543518319544825700191924850016351970295432362115448292821701667182186922608417526375411952522351186935715718643976841768956006
The reason your first method didn't change the file is because all files are stored in the same way. The only "difference" between text files and binary files is that text files contain only bytes that can be shown as ASCII characters, while binary files* have a much more random variety and order of bytes. So you are reading bytes in as bytes and then outputting them as bytes again!
*I'm including Unicode text files as binary, since they can have multiple bytes to denote one character point, depending on the character point and the encoding used.
The second method is also fairly simple. You are reading in the bytes, as before, and storing them in integers (which are probably 4 bytes long). Then you are just printing out the integers as if they are integers, so you are seeing a string of numbers.
As for why your first method cut off some of the bytes, you're right in that it's probably some bug in your code. I thought it was more important to explain what the ideas are in this case, rather than debug some test code.