C - Reverse Converter Process - c

Context:
I'm trying to reverse the process of a c converter. This is the original converter:
#include <stdio.h>
int main(void) {
FILE *f = fopen("input.bin", "rb");
fseek(f, 0, SEEK_END);
int s = ftell(f);
rewind(f);
FILE *o = fopen("output.txt", "wb");
int i;
for(i = 0; i < s / 4; i++) {
unsigned int u;
fread(&u, sizeof(u), 1, f);
fprintf(o, "u32[%d] = 0x%08x;\n", i, u);
}
fclose(o);
fclose(f);
return 0;
}
What it does is it creates a new file called output.txt and converts the .bin file to bytes in a order like this:
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
Question:
Now, what I'm trying to do is the opposite. So, I'm trying to convert the output bytes of the above converter to a .bin file again, like its original state.
I tried this, but I'm stuck on the loop part:
#include <stdio.h>
int main(void) {
FILE *f = fopen("loader.txt", "rb"); // INPUT
fseek(f, 0, SEEK_END);
int s = ftell(f);
rewind(f);
FILE *o = fopen("loader.bin", "wb"); // OUTPUT
int i;
for(i = 0; i < s / 4; i++) {
// grab u32 bytes from loader.txt and convert into a .bin
}
fclose(o);
fclose(f);
return 0;
}
Can anyone help me out with this? Would be amazingly appriciated.
Edit
#include <stdio.h>
int main(void) {
FILE *f = fopen("loader.txt", "rb"); // INPUT
rewind(f);
FILE *o = fopen("loader.bin", "wb"); // OUTPUT
int i;
for(i = 0; i < s / 4; i++) {
fgets(f);
sscanf(f);
}
fclose(o);
fclose(f);
return 0;
}

Here is code which seems to do the job:
#include <stdio.h>
int main(void)
{
const char i_file[] = "loader.txt";
const char o_file[] = "loader.bin";
FILE *f = fopen(i_file, "rb"); // INPUT
if (f == 0)
{
fprintf(stderr, "failed to open file '%s' for reading\n", i_file);
return 1;
}
FILE *o = fopen(o_file, "wb"); // OUTPUT
if (o == 0)
{
fprintf(stderr, "failed to open file '%s' for writing\n", o_file);
return 1;
}
char line[1024];
int lineno = 0;
while (fgets(line, sizeof(line), f) != 0)
{
int u32num;
unsigned int value;
lineno++;
if (line[0] == '\n')
continue; // Blank lines ignored
if (sscanf(line, "u32[%d] = %x", &u32num, &value) == 2)
{
fseek(o, u32num * sizeof(value), SEEK_SET);
if (fwrite(&value, sizeof(value), 1, o) != 1)
{
fprintf(stderr, "Failed to write 0x%.8X to offset %d in %s\n",
value, u32num, o_file);
break;
}
}
else
{
fprintf(stderr, "Input line %d in %s is mal-formatted: %s", lineno, i_file, line);
break;
}
}
fclose(o);
fclose(f);
return 0;
}
When run on the sample data from the question (loader.txt):
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
the output file (loader.bin) is:
$ odx loader.bin
0x0000: 41 54 55 53 48 B8 73 63 65 4E 65 74 53 6F 48 83 ATUSH.sceNetSoH.
0x0010: EC 60 BE 0E 00 00 00 48 8D 5C 24 40 48 89 44 24 .`.....H.\$#H.D$
0x0020: 40 48 89 DA 48 8D 4C 24 10 BF 4F 02 00 00 31 C0 #H..H.L$..O...1.
0x0030: C7 44 24 48 63 6B 65 74 .D$Hcket
0x0038:
$
where odx is simply a home-grown hex dump program (you could use od or xxd or other programs to achieve similar results). Taking the original conversion code verbatim (it compiled cleanly under my stringent compilation options — well done), and copying loader.bin to input.bin, the output is:
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
This is the same as the original input file, so the pair of programs can round-trip their data (run the two programs in turn and get as final output the data stored as the original input). Note that the code has not been tested on a binary file with a length that is not a multiple of 4 bytes; there are issues to worry about there.

Related

Writing half of an int array into a new text file

In my program, I am trying to opens the text file provided at the command-line, and then creates two new text files values1.txt and values2.txt. The file from the command line contains 100 unique integer numbers. Half of the numbers are copied into values1.txt, the other half is copied into values2.txt.
However, when I tried to do it for values1.txt, I got the following values:
101
32758
0
0
176197744
32764
3
0
176197728
32764
0
0
-78325960
32758
0
0
1
0
-78326000
32758
0
0
1700966438
0
-78325096
32758
176197896
32764
176197952
32764
-78326000
32758
0
0
-80547345
32758
0
0
176197952
32764
0
0
0
0
0
0
-78326000
32758
-82942073
32758
8
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int cfileexists(const char * filename){
/* try to open file to read */
FILE *file;
if (file = fopen(filename, "r")){
fclose(file);
return 1;
}
}
int main(int argc,char*argv[]){
char *p= argv[1];
int numArray[100];
int i=0;
int sum1arr[50];
int sum2arr[50];
if (! cfileexists(p)){
printf("Error, unable to locate the data file %s\n", p);
return 100;
}
for(i;i<100;i++){
FILE *stream=fopen(p,"r");
while(!feof(stream)){
fscanf(stream,"%d",&numArray[i]);
}
FILE * fPtr = NULL;
fPtr = fopen("values1.txt", "w");
for(int j=0;j<50;j++){
fprintf(fPtr,"%d\n",numArray[j]);
}
}
}
For comparison; this is the source txtfile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
The for statement has too many cycles, you should use the read cycle to also write, you also can use fscanf return to verify whe the file reaches it's end. If you don't need to save the values you can even use on singe int to temporarily store the value till it's written.
Here is a possibe implementation with comments:
Live demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cfileexists(const char *filename)
{
/* try to open file to read */
FILE *file;
if ((file = fopen(filename, "r")))
{
fclose(file);
return 1;
}
return 0; //return 0 if file not found
}
int main(int argc, char *argv[])
{
if(argc != 2){ //check number of arguments
puts("Wrong number of arguments");
return(EXIT_FAILURE); //EXIT_FAILURE macro is more portable
}
FILE *stream;
FILE *fPtr = NULL;
FILE *fPtr2 = NULL;
int numArray[100];
int i = 0;
fPtr = fopen("values1.txt", "w");
fPtr2 = fopen("values2.txt", "w");
//you can use fopen to check file nstead of the
//function, it returns null if no file is opened
if (!(stream = fopen(argv[1], "r")))
{
perror("Error, unable to locate the data file"); //also prints error signature
return EXIT_FAILURE;
}
//check input, stop when there is nothing else to read
while (fscanf(stream, "%d", &numArray[i]) == 1 && i < 100)
{
if(i < 50)
fprintf(fPtr, "%d\n", numArray[i]); //write to file 1
else
fprintf(fPtr2, "%d\n", numArray[i]); //write to file 2
i++;
}
fclose(stream);
fclose(fPtr);
fclose(fPtr2);
}
Here's a different approach that uses getline():
#include <stdio.h>
#include <stdlib.h>
#define SPLIT_POINT 50
int main(void) {
char filename[] = "test";
FILE *fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "Couldn't open %s\n", filename);
}
// Check file open (as above) left out for brevity
FILE *out1 = fopen("values1.txt", "w");
FILE *out2 = fopen("values2.txt", "w");
char *line = NULL;
size_t n = 0, i = 0;
ssize_t len = 0;
while ((len = getline(&line, &n, fp)) != EOF) {
// Select which output file to write to
FILE *out = i < SPLIT_POINT ? out1 : out2;
// getline includes the newline - remove this
if (i == SPLIT_POINT - 1 && len > 0) {
line[--len] = 0;
}
// Write to the relevant output file
fprintf(out, "%s", line);
i++;
}
fclose(fp);
fclose(out1);
fclose(out2);
free(line);
return 0;
}
If you don't care about removing newlines, you could simplify the getline() call - just don't bother with the len variable.

Read values from a binary file in C

this is my problem: I don't know how to read the integers from a binary file. I need a solution for understand the problem behind the code.
This is the image of my binary file:
This is a format to memorize 32 bit integers in little endian. For example we have a file with 3 values: 1, 2 and 3, with this format they willl be codified in:
01 00 00 00 02 00 00 00 03 00 00 00 or 01 FF FF FF ... .
I wrote some line of code and I do not understand why it does not work. The debug don't give me errors.
This is my code
#include <stdlib.h>
#include <stdio.h>
int *leggiinteri2(const char *filename, size_t *size)
{
FILE *f;
int *p = NULL;
f = fopen(filename, "rb");
if (f == NULL) {
p = NULL;
}
else {
size_t nInteri = fread(size, sizeof(int), 1, f);
if (nInteri != 1) {
if (feof(f)) {
p = NULL;
}
if (ferror(f)) {
p = NULL;
}
}
else {
p = malloc(sizeof(int)*((int)size));
fseek(f, 0, SEEK_SET);
nInteri = fread(p, sizeof(int), *size, f);
if (nInteri != *size) {
if (feof(f)) {
p = NULL;
}
if (ferror(f)) {
p = NULL;
}
}
}
}
fclose(f);
return p;
}
Try some thing like:
fread (buffer, sizeof(char), 8, fid);
x = (s32)(((buffer[0]<<24) & 0xFF000000) + ((buffer[1]<<16) & 0x00FF0000)
+ ((buffer[2]<< 8) & 0x0000FF00) + ( buffer[3] & 0x000000FF));
I am not sure of the order (little or big endian). If KO, reverse the buffer indice 3, 2, 1, 0.
I finally found the solution, it took a lot of time but it was worth it, now I understand the logic behind it.
This is the code for those who need it:
#include <stdlib.h>
#include <stdio.h>
int *leggiinteri2(const char *filename, size_t *size)
{
FILE *f;
int *p = NULL;
f = fopen(filename, "rb");
if (f == NULL) {
p = NULL;
}
else {
fseek(f, 0, SEEK_END); //It tells me how many values ​​there are in
//the file, both those that I need and those
//that do not
long dim = ftell(f); // I assign to dim the value that tells me
//ftell, conditioned by the previous function
dim = dim / 4; //because I want the integer values (int = 4 bytes)
*size = dim;
p = malloc(sizeof(int) * dim);
fseek(f, 0, 0);
size_t n = fread(p, sizeof(int), *size, f);
if (n != *size) {
if (feof(f)) {
p = NULL;
}
if (ferror(f)) {
p = NULL;
}
}
if (n == 0) //serves to check for empty or NULL files
p = NULL;
}
fclose(f);
return p;
}

Reading from file in C including char and integer

How to read and store each column in the following text from a file into an array
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
The first column should be string and the rest should be integer
Here is a simple code that do the job.
First put your text inside a test.txt file, save it in C source code path.
test.txt
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
Code
#include <stdio.h>
int main (void)
{
FILE *fp = NULL;
char *line = NULL;
size_t len = 0;
size_t read = 0;
char string[10][32];
int a[10], b[10], c[10];
int count = 0;
fp = fopen("test.txt", "r");
if(fp != NULL){
while((read = getline(&line, &len, fp)) != -1){
sscanf(line, "%s%d%d%d", string[count], &a[count], &b[count], &c[count]);
printf("<%s> - <%d> - <%d> - <%d>\n", string[count], a[count], b[count], c[count]);
count++;
}
}else{
printf("File can't open\n");
}
return 0;
}
Compile, Run
gcc -Wall -Wextra te.c -o te
./te
If you have more than 10 lines you should increase the arrays dimension.
Hope this help you.

Parsing and splitting a string from txt file in C

I'm new into C and I got an assignment to read line by line from .txt file and parse some strings into matrix where first line is first row, second line is second row etc. This is what I have in my text.txt file:
07 45 C4 16 0F 02 19 0I 17 0G
09 45 C4 15 0E 03 11 0A 12 0B 13 0C
13 45 C4 13 0C 03 19 0I 11 0A 17 0G 14 0D 16 0F
05 45 C4 18 0H 01 12 0B
This is what I was able to do so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *Read(char filename[]);
void split(char *content);
int main(void){
char filename[] = "text.txt";
char *content = Read(filename);
split(content);
return 0;
}
char *Read(char filename[]){
char *buffer;
long size;
FILE *log = fopen("text.txt", "r");
fseek(log, 0, SEEK_END);
size = ftell(log);
rewind(log);
buffer = (char*) malloc(sizeof(char) * size);
fread(buffer, 1, size, log);
fclose(log);
return buffer;
}
void split(char *content){
char *buffer = strtok(content, " ");
while(buffer != NULL){
printf("%s\n", buffer);
buffer = strtok (NULL, " ");
}
}
I would really appreciate comments in code because I'm rookie and it would help me to better understand some things.
To give you an idea of how it works, I wrote this snippet which manually read the line in that array, supposing that we already know the desired results.
The following approach cannot be considered the right one. Ideally you would have a series of rules to split the string, in the following however you have to set the scanf format manually for each line that you want to read.
Remember to check the return value of scanf, here we should ensure that we have read 7 elements.
int main(void) {
FILE *log;
char buffer[SIZE];
char line[SIZE];
char array[10][10];
if ((log = fopen("text.txt", "r")) == NULL){
fprintf(stderr, "Can't open input file!\n");
return(1);
}
while(fgets(buffer, sizeof(buffer), log)){
int ret = sscanf(buffer, "%2s%2s%2s%4s%2s%4s%4s", array[0], array[1], array[2], array[3], array[4],array[5], array[6]);
printf("read %d elements\n", ret);
if (ret != 7) {
return(1);
}
printf("%s", buffer);
}
int i;
for (i=0; i < 6; i++)
printf("%s\n", array[i]);
fclose(log);
return 0;
}

Compress hex data

For university I have the exercise to compress a series of data. In one file there is the input data and I have to write another one with the compressed data. The task is only to store the difference between the numbers. Until now I have the written the code that stores the data in an array and stores the same in the output file. Now I want to start with the compression, but have no clue how to do it. Did I store the data type?
The input file could look like this:
C9 CB C7 C0 C0 C8 C9 C9 BE 00 04
So the output file has to look like this:
C9 C2 90 8C 81 08 BE 80 04
int main(int argc, char **argv) {
if (argc < 3)
{
fprintf(stderr, "Usage: input.txt output.txt\n");
return EXIT_FAILURE;
}
FILE *input, *output;
input = fopen(argv[1], "r");
output = fopen(argv[2], "w");
int c;
unsigned int values[100] = { 0 };
int i = 0;
if (input != NULL)
{
printf("Values:\n");
while ((c = fgetc(input)) != EOF)
{
values[i] = c;
putchar(c);
i++;
}
printf("\n");
fclose(input);
}
else
{
fprintf(stderr, "File could not be opened.\n");
return EXIT_FAILURE;
}
if (output != NULL)
{
int j = 0;
for (j; j < i; j++)
{
putc(values[j], output);
}
fclose(output);
}
else
{
fprintf(stderr, "Could not generate output file.\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Resources