Read values from a binary file in C - 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;
}

Related

Can't read null terminated string from binary file in C

I have a which is launched in repl.it. The problem is that is doesn't properly reads null-terminated string from the file:
x == 228
y == Hell
x == 228
y == #
The last line should be y == Hell. How to fix my code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct A {
int x;
char *y;
};
#define INITIAL_BUFFER_LENGTH 10
char *read_string_from_file(FILE *handle) {
int string_capacity = 10;
char *string = malloc(string_capacity);
int count = 0;
char c;
while ((c = fgetc(handle)) != '\0') {
string[count] = c;
count++;
if (count == string_capacity) {
string_capacity *= 2;
string = realloc(string, string_capacity);
}
}
string[count] = '\0';
return string;
}
int main(void) {
struct A *obj = (struct A *)malloc(sizeof(struct A));
obj->x = 228;
obj->y = "Hell";
printf("x == %i\n", obj->x);
printf("y == %s\n", obj->y);
FILE *file = fopen("f.txt", "w");
fwrite(&obj->x, sizeof(obj->x), 1, file);
fwrite(&obj->y, strlen(obj->y) + 1, 1, file);
fclose(file);
obj->x = 0;
obj->y = NULL;
file = fopen("f.txt", "r");
fread(&obj->x, sizeof(obj->x), 1, file);
obj->y = read_string_from_file(file);
printf("x == %i\n", obj->x); // must be 228
printf("y == %s\n", obj->y); // must be Hell
return 0;
}
The relevant line is this one:
fwrite(&obj->y, strlen(obj->y) + 1, 1, file);
With this, you write the address of a pointer to the file.
What you want instead, is to write where the pointer points to:
fwrite(obj->y, strlen(obj->y) + 1, 1, file);

Having malloc(): corrupted top size issue

I am trying to write code to test the speed of lz4 compression instead of using -b code in terminal.
I am using ubuntu Ubuntu 20.04.2 LTS. And visual studio ide.
Here is my code, it has some trouble when running the second time of the for loop in main.
This line:
fread(src,16384,1,fc);
When i = 1, it works as I expected. However, when i = 2, the malloc() problem just pop up.
//The split file function works perfectly.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lz4.h"
int splitFile(char* fileIn, size_t maxSize);
#include "lz4.c"
int main()
{
time_t start,end;
int compress, decompress;
int64_t num_f=0;
int64_t i;
char* src=malloc(16384);
int srcSize= 16385;//(int)(strlen(src) + 1);
int dstCapacity=0;
int compressed_data_size=0;
char* compressed_data = malloc((size_t)dstCapacity);
char buff[200];
FILE * fc;
num_f = splitFile("/home/ziruo/research/1stpro/test.txt",16384);
printf("num_f=%ld\n",num_f);
start = time(NULL);
for( i = 1; i <= num_f; i++)
{
sprintf(buff,"/home/ziruo/research/1stpro/test.txt.%03d",i);
printf("buff %s\n",&buff);
if (compressed_data == NULL)
{
printf("faild to generae storage\n");
}
fc = fopen(buff,"r");
printf("fc is: %d\n",fc);
fread(src,16384,1,fc);
srcSize=(int)(strlen(src) + 1);
dstCapacity= LZ4_compressBound(srcSize)
compressed_data_size = LZ4_compress_default(src,compressed_data,srcSize,dstCapacity);
LZ4_compress_default(src,compressed_data,srcSize,dstCapacity);
printf("data size ratio %.2f\n", (float)compressed_data_size/srcSize);
}
end = time(NULL);
printf("time used(s): %f\n",difftime(end,start));
return 0;
}
int splitFile(char* fileIn, size_t maxSize)
{
int result = 0;
FILE* fIn;
FILE* fOut;
char buffer[1024 * 16];
size_t size;
size_t read;
size_t written;
if ((fileIn != NULL) && (maxSize > 0))
{
fIn = fopen(fileIn, "rb");
if (fIn != NULL)
{
fOut = NULL;
result = 1; // we have at least one part
while (!feof(fIn))
{
// initialize (next) output file if no output file opened
if (fOut == NULL)
{
sprintf(buffer, "%s.%03d", fileIn, result);
fOut = fopen(buffer, "wb");
if (fOut == NULL)
{
result = -1;
break;
}
size = 0;
}
// calculate size of data to be read from input file in order to not exceed maxSize
read = sizeof(buffer);
if ((size + read) > maxSize)
{
read = maxSize - size;
}
// read data from input file
read = fread(buffer, 1, read, fIn);
if (read == 0)
{
result = -1;
break;
}
// write data to output file
written = fwrite(buffer, 1, read, fOut);
if (written != read)
{
result = -1;
break;
}
// update size counter of current output file
size += written;
if (size >= maxSize) // next split?
{
fclose(fOut);
fOut = NULL;
result++;
}
}
// clean up
if (fOut != NULL)
{
fclose(fOut);
}
fclose(fIn);
}
}
return (result);
}
And here is the picture of error
enter image description here

Corrupted data when using a multidimensional char array

I'm currently implementing a function to use the "external sort" method because I have to sort a big file (+200K lines) on a device with low RAM, right now just trying to make it run on a windows pc.
I'm working on the function to split the file in tiny sorted files.
The problem I'm facing is that among the tiny sorted files the function creates, the data on certain lines are truncated.
I'm quite sure I've done a mistake somewhere but was not able to find it, yet. Could you help me to discover the problem please ?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE_LEN 50
#define MAX_LINES_SORTED 130
void createSortedFiles(FILE*);
int main()
{
FILE *fp = fopen("C:\\C\\Tests\\1.txt", "r+");
if(fp == NULL){
printf("Error opening fp");
return 1;
}
createSortedFiles(fp);
fclose(fp);
return 0;
}
int cmp(const void *p1, const void *p2) {
return strcmp(p1, p2);
}
void createSortedFiles(FILE* fp) {
FILE* sfp;
//FILE* sfp2 = fopen("C:\\C\\Tests\\test.txt", "w+");
char lines[MAX_LINES_SORTED][MAX_LINE_LEN + 1] = {0}, buffer[MAX_LINE_LEN + 1] = { 0 }, fnum[6];
char fname[20] = "C:\\C\\Tests\\";
char *p;
int i = 0, j = 0 /*file names*/, int max_lines = MAX_LINES_SORTED - 1;
size_t N;
while (1){
p = fgets(buffer, MAX_LINE_LEN, fp);
// fwrite(buffer, strlen(buffer), 1, sfp2);
if(strlen(buffer) > 0 || i > 0){
if(p != NULL)
memcpy(lines[i], buffer, strlen(buffer));
//If reached the max number of lines accepted in the array
//Or reached EOF
//=> Sort and write the array "lines"
if (i >= max_lines || p == NULL) {
N = sizeof(lines) / sizeof(lines[0]);
qsort(lines, N, sizeof(*lines), cmp);
//sets the name of the current file
memset(&fname[11], 0, 9);
itoa(j, fnum, 10);
strcat(fname, fnum);
if ((sfp = fopen(fname, "w+")) == NULL) {
printf("Error opening sfp");
return;
}
for (i = 0; i < N; i++) {
fwrite(lines[i], strlen(lines[i]), 1, sfp);
}
fclose(sfp);
memset(lines, 0, sizeof(lines[0][0]) * MAX_LINES_SORTED * MAX_LINE_LEN);
j++; i = -1; //because incremented right after
}
}
if(p == NULL){
break;
}
i++;
}
//fclose(sfp2);
return;
}
Here's an example of the fp file (each lines ending with \r\n):
8023796280724;00060-014.W47
8023796280731;00060-014.W48
;0009070305/08007
;0009470337/08007
;0009490338/13001
;0010480311/08007
;0010830308/08007
;0011S
8033280129293;002004GRS4XL
;002015RSM
5708628117005;00207-630-06T42
5708628117012;00207-630-06T44
5708628117036;00207-630-06T46
4051428088756;647530241000045
4051428088763;647530241000046
4051428088770;647530241000047
;647BLPMF
4051428092586;648510256000040
4051428092593;648510256000041
4051428092609;648510256000042
4051428092616;648510256000043
4051428092623;648510256000044
4051428092630;648510256000045
4051428092647;648510256000046
Your "truncated lines" are not really truncated lines, they are stray data left in the buffer from previous files.
This array:
#define MAX_LINE_LEN 50
#define MAX_LINES_SORTED 130
char lines[MAX_LINES_SORTED][MAX_LINE_LEN + 1];
has 6630 bytes, but here:
memset(lines, 0, sizeof(lines[0][0]) * MAX_LINES_SORTED * MAX_LINE_LEN);
you zero out only 6500 bytes and leave the last two lines as they are.
You can fix this by using (MAX_LINE_LEN +1) in the size calculation, but the array can be zeroes out more tersely (and more reliably) with just:
memset(lines, 0, sizeof(lines));

C - Reverse Converter Process

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.

Dividing a file into equal parts of 128 bytes each

int main()
{
FILE *fe, *fs;
unsigned char buffer[128];
int bytesreader;
int i;
char cad[100];
fe = fopen("pg2000.txt", "rb");
fseek(fe, 0L, SEEK_END);
int x = ftell(fe);
printf("%d",x);
int x = ftell(fe);
int result=x/128;
for(i=0;i<result;i++)
{
bytesreader = fread(buffer, 1, 128, fe)
sprintf(cad, "a%d", i);
strcat(cad,".txt");
printf("%s\n", cad);
fs = fopen(cad, "wb");
fwrite(buffer, 1, bytesreader, fs);
fclose(fs);
}
fclose(fe);
return 0;
}
I want to split a file into equal parts of 128 bytes each, but when the file is large I get a access violation, I don't understand...
fe = fopen("pg2000.txt", "rb");
int x = ftell(fe);
int result=x/128;
x here will be zero. If the fopen() suceeds. Which you need to check for.
Also, as WhozCraig points out, the fclose() for fs should be inside your loop.
And this
for(i=0;i=result;i++)
^
Is probably not exactly what you had in mind either.

Resources