i want to decode an ASN.1 standard binary file. i have converted the binary file to hex and stored it in a file. now i want to convert this hex to ascii. The problem im having now is how to read the hex file.
the file looks this way,
81 01 32 82 0D 35 31 34 32 34 31 38 38 38 where 81 is a header, 01 is the size and 32 is the data. again 82 is the header and this goes on. how do i read from this file and differentiate between the various fields present.
i searched all over the internet for this, but couldnt get a satisfactory answer. so can someone help me with the way forward . i dont want any code, just want the procedure how i can do it.
I would first read the header and then in a loop the data. You can read hexadecimal numbers with the "x"-specifier (say your file is named hexfile.txt):
#include <stdio.h>
int main ()
{
FILE *stream;
unsigned int h, l, d;
if( (stream = fopen( "hexfile.txt", "r" )) == NULL ) return 1;
while (EOF != fscanf (stream, " %x %x", &h, &l))
{
printf ("%02X %02X\n",h,l);
for (unsigned i=0; i<l; ++i)
{
if (EOF == fscanf (stream, " %x", &d)) break;
printf ("%02X ",d);
}
puts ("");
}
fclose (stream);
return 0;
}
Related
I have a text file, where each line is an integer with a newline character. I also have a .bin file with the same thing.
10
20
30
40
50
60
70
Running this code...
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int input;
FILE *infile_t = fopen("numbers.txt", "r");
FILE *infile_b = fopen("numbers.bin", "rb");
if (infile_t == NULL) {
printf("Error: unable to open file %s\n", "numbers.txt");
exit(1);
}
if (infile_b == NULL) {
printf("Error: unable to open file %s\n", "numbers.bin");
exit(1);
}
printf("Enter an integer index: ");
while(scanf("%d",&input) != EOF){
int ch;
fseek(infile_t, (input*sizeof(int))-1, SEEK_SET);
fscanf(infile_t, "In text file: %d\n", &ch);
printf("In text file: %d\n", ch);
fseek(infile_b, (input*sizeof(int))-1, SEEK_SET);
fscanf(infile_b, "%d\n", &ch);
printf("In binary file: %d\n", ch);
printf("Enter an integer index: ");
}
fclose(infile_t);
fclose(infile_b);
return 0;
}
and entering 0, 1, 2, 3, 4 consecutively, I get the outputs:
10
0
40
50
0
I am trying to read the file by 4 bytes at a time (each int) and print the integer. What am I doing wrong and if this is bad practice, what would be better?
There is a difference between the textual representation of numbers and their binary representation.
Your input is a text file, which is a sequence of characters:
"10lf20lf30lf40lf50lf60lf70lf"
Its size is 21 bytes, which you could check with your file explorer.
And as bytes in a tabular form it looks like this, assumed that you are using ASCII and a unix-like system:
Offset
Bytes
Text
0
31 30 0A
"10lf"
3
32 30 0A
"20lf"
6
33 30 0A
"30lf"
9
34 30 0A
"40lf"
12
35 30 0A
"50lf"
15
36 30 0A
"60lf"
18
37 30 0A
"70lf"
There are no integers stored in binary form in your input file.
The function fseek() places the "cursor" into the file at the specified offset.
Then you call scanf() to scan and interpret(!) the sequence of characters that start at that offset.
Input
Offset set by fseek()
Text
Resulting value
0
0
"10lf..."
10
1
4
"0lf..."
0
2
8
"lf40lf..."
40
3
12
"50lf..."
50
4
16
"0lf..."
0
Since scanf() skips leading whitespace, you get "40" in the third case.
You cannot use fseek() in the general case to "jump" to a certain line in a text file. Except, that you know how long each line is. In your case this is known, and if you use a factor of 3 instead of 4, you will get what you seem to want.
I don't know what is in your 'numbers.bin', and you opened 'numbers.txt' as infile_t but didn't use it.
Assuming that the content in 'numbers.bin' is the text content in your question, and you open it in binary mode for reading, the contents stored in the file are as follows(end with one byte '\n' instead of two bytes '\r\n'):
\x31\x30\x0a\x32\x30\x0a\x33\x30\x0a\x34\x30\x0a\x35\x30\x0a\x36\x30\x0a\x37\x30
At this time, the file pointer is at the head of the file, pointing to the text content '1'(ascii code is 0x31).
\x31\x30\x0a\x32\x30\x0a\x33\x30\x0a\x34\x30\x0a\x35\x30\x0a\x36\x30\x0a\x37\x30
↑
when you use scanf("%d",&input) and input '0', the integer variable input will be 0, then you set the file pointer via fseek(infile_b, input*4, SEEK_SET), the file pointer will point to offset 0 relative to the beginning of the file.
Next line fscanf(infile_b, "%d\n", &ch) will read a integer value to variable ch, then ch will store the value 10 and print it to standard output (stdout) via printf.
When you enter '1', the file pointer will be set to 4, which will point to the fifth byte position relative to the beginning of the file, as follows:
\x31\x30\x0a\x32\x30\x0a\x33\x30\x0a\x34\x30\x0a\x35\x30\x0a\x36\x30\x0a\x37\x30
↑
The ascii code of the text value '0' is 0x30. It will read an integer value 0 and store it in ch.
You can replace fseek(infile_b, input*4, SEEK_SET) with fseek(infile_b, input*3, SEEK_SET), and will get the expected output.
Can anyone explain me whats exactly going on here?
I have a problem in file management.
Explanation of code:
Here, it takes integers from user and then stored in DATA file.
then it reads integers from DATA file and filter them by ODD and EVEN and store it respective file.
Here is my code.
#include<stdio.h>
int main()
{
FILE *f1, *f2, *f3;
int number;
printf("Enter the content of data file\n");
f1 = fopen("DATA","w");
for(int i=1;i<=30;i++)
{
/*problem is here*/
number=getw(stdin);
//scanf("%d",&number);
if(number==-1 || number==EOF) break;
putw(number,f1);
}
fclose(f1);
f1 = fopen("DATA","r");
f2 = fopen("ODD","w");
f3 = fopen("EVEN","w");
while((number = getw(f1))!=EOF)
{
if(number % 2 == 0)
putw(number, f3);
else
putw(number,f2);
}
fclose(f1);
fclose(f2);
fclose(f3);
f2 = fopen("ODD","r");
f3 = fopen("EVEN","r");
printf("\n\ncontents of ODD file\n");
while((number=getw(f2))!=EOF)
/* problem is here */
putw(number,stdout);
//fprintf(stdout,"%d\n",number);
//printf("%d",number);
printf("\n\ncontents of EVEN file\n");
while((number=getw(f3))!=EOF)
/*problem is here */
//putw(number,stdout);
fprintf(stdout,"%d\n",number);
//printf("%d",number);
fclose(f2);
fclose(f3);
printf("\n");
return 0;
}
Output:
Enter the content of data file
111
222
333
444
555
contents of ODD file
111
333
555
contents of EVEN file
171061810
171193396
So here, why putw shows correct output with getw, and fprintf and printf only shows correct output with scanf. However, data stored in all files are correct!!!
why is it so?
why putw shows correct output with getw, and fprintf and printf only shows correct output with scanf
Because the getw() function reads the next word from the stream. The size of a word is the size of an int and may vary from machine to machine`
You can see in the comment: 171061810 is 0xA323232 (it's a hex number). When you use the ASCII code to convert from hex to character, you get:
Hex Character
A ==> \n
32 ==> 2
32 ==> 2
32 ==> 2
so
171061810 is "\n222".
It's similar to 444.
I am trying to run my code on eclipse with ubuntu.
I have dumped the data using fprintf into one txt file and reading that file by using fscanf. I am not able to read that values into data array.
Below is my code :
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main(){
char* data;
FILE *fp;
size_t result;
data = (char*) malloc (sizeof(char)*(1280*800));//Size of one frame
if (data==NULL){
printf("NOt able to allocate memory properly\n");
exit (1);
}
fp = fopen ("\\home\\studinstru\\Desktop\\filedump.txt", "r");
if(fp==NULL){
printf("Error in creating dump file\n");
exit (1);
}
for(int m = 0;m<1280;m++){
for(int n = 0;n<800;n++){
fscanf(fp,"%d/t",data[m*800 + n]);
}
}
fclose(fp);
return 0;
}
This is my filedump.txt data :
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82 ....
Can you tell what is wrong in this?
Your code has a couble of problems
Your fscanf() format is wrong and you are passing the value instead of it's address, you should use
fscanf(fp, "%d", &data[n + 800 * m]);
if you meant "\t" whcih is the tab character, it's not needed anyway and passing the value instead of it's address is Undefined Behavior, because fscanf() will treat the value as a pointer, and it's not likely pointing to a valid memory address, moreover, it's unintialized which is another reason for undefined behavior.
You declared data as char *data and store int's in it, that is also Undefined Behavior.
You must check the return value of fscanf() beacuse if it fails, then the value will be uninitialized and there will be once again, Undefined Behavior and also you are going to read past the end of the file because you will never know if you reached it.
You are writing into the file and you open it for reading, this
fprintf(fp, "\n");
is wrong, you don't need it to read from the file.
Don't cast the result of malloc() though this is not causing problems in this case, it will improve the quality of your code.
Don't use sizeof(char) it makes your code harder to read and it's completely unnecessary since the standard mandates that sizeof(char) == 1.
You don't need the nested loop to read the data, because the shape of the data is irrelevant since fscanf() ignores all whitespace characters.
It is sufficient to read throug the file and use a counter to move through the array, at the end you can check how many values where read to verify the integrity of the data.
This is a fixed version of your code
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main()
{
FILE *fp;
size_t index;
int *data;
data = malloc(1280 * 800);
if (data == NULL)
{
printf("NOt able to allocate memory properly\n");
return 1;
}
fp = fopen("\\home\\studinstru\\Desktop\\filedump.txt", "r");
if (fp == NULL)
{
printf("Error in creating dump file\n");
free(data);
return 2;
}
while (fscanf(fp, "%d", &data[index]) == 1)
{
fprintf(stdout, "%d ", data[index]);
index += 1;
if (index % 800 == 0)
printf("\n");
}
fclose(fp);
return 0;
}
Note: I recommend the use of compiler warnings, they would help prevent silly mistakes and some other mistakes like char *data and reading int's into it.
Also, from your file path "\\home\\studinstru\\Desktop\\filedump.txt" it seems you are on a non-windows system, and very likely the directory separator is / instead of \, so the correct path has to be
"/home/studinstru/Desktop/filedump.txt"
Replace
fscanf(fp,"%d/t",data[m*800 + n]);
with
fscanf(fp,"%d/t",&data[m*800 + n]);
fscanf() needs address of destination variable as argument and not the variable itself.
Also I am not getting why are doing this:
fprintf(fp,"\n");
Does anyone have an example of code that can write to a binary file. And also code that can read a binary file and output to screen. Looking at examples I can write to a file ok But when I try to read from a file it is not outputting correctly.
Reading and writing binary files is pretty much the same as any other file, the only difference is how you open it:
unsigned char buffer[10];
FILE *ptr;
ptr = fopen("test.bin","rb"); // r for read, b for binary
fread(buffer,sizeof(buffer),1,ptr); // read 10 bytes to our buffer
You said you can read it, but it's not outputting correctly... keep in mind that when you "output" this data, you're not reading ASCII, so it's not like printing a string to the screen:
for(int i = 0; i<10; i++)
printf("%u ", buffer[i]); // prints a series of bytes
Writing to a file is pretty much the same, with the exception that you're using fwrite() instead of fread():
FILE *write_ptr;
write_ptr = fopen("test.bin","wb"); // w for write, b for binary
fwrite(buffer,sizeof(buffer),1,write_ptr); // write 10 bytes from our buffer
Since we're talking Linux.. there's an easy way to do a sanity check. Install hexdump on your system (if it's not already on there) and dump your file:
mike#mike-VirtualBox:~/C$ hexdump test.bin
0000000 457f 464c 0102 0001 0000 0000 0000 0000
0000010 0001 003e 0001 0000 0000 0000 0000 0000
...
Now compare that to your output:
mike#mike-VirtualBox:~/C$ ./a.out
127 69 76 70 2 1 1 0 0 0
hmm, maybe change the printf to a %x to make this a little clearer:
mike#mike-VirtualBox:~/C$ ./a.out
7F 45 4C 46 2 1 1 0 0 0
Hey, look! The data matches up now*. Awesome, we must be reading the binary file correctly!
*Note the bytes are just swapped on the output but that data is correct, you can adjust for this sort of thing
There are a few ways to do it. If I want to read and write binary I usually use open(), read(), write(), close(). Which are completely different than doing a byte at a time. You work with integer file descriptors instead of FILE * variables. fileno will get an integer descriptor from a FILE * BTW. You read a buffer full of data, say 32k bytes at once. The buffer is really an array which you can read from really fast because it's in memory. And reading and writing many bytes at once is faster than one at a time. It's called a blockread in Pascal I think, but read() is the C equivalent.
I looked but I don't have any examples handy. OK, these aren't ideal because they also are doing stuff with JPEG images. Here's a read, you probably only care about the part from open() to close(). fbuf is the array to read into,
sb.st_size is the file size in bytes from a stat() call.
fd = open(MASKFNAME,O_RDONLY);
if (fd != -1) {
read(fd,fbuf,sb.st_size);
close(fd);
splitmask(fbuf,(uint32_t)sb.st_size); // look at lines, etc
have_mask = 1;
}
Here's a write: (here pix is the byte array, jwidth and jheight are the JPEG width and height so for RGB color we write height * width * 3 color bytes). It's the # of bytes to write.
void simpdump(uint8_t *pix, char *nm) { // makes a raw aka .data file
int sdfd;
sdfd = open(nm,O_WRONLY | O_CREAT);
if (sdfd == -1) {
printf("bad open\n");
exit(-1);
}
printf("width: %i height: %i\n",jwidth,jheight); // to the console
write(sdfd,pix,(jwidth*jheight*3));
close(sdfd);
}
Look at man 2 open, also read, write, close. Also this old-style jpeg example.c: https://github.com/LuaDist/libjpeg/blob/master/example.c I'm reading and writing an entire image at once here. But they're binary reads and writes of bytes, just a lot at once.
"But when I try to read from a file it is not outputting correctly." Hmmm. If you read a number 65 that's (decimal) ASCII for an A. Maybe you should look at man ascii too. If you want a 1 that's ASCII 0x31. A char variable is a tiny 8-bit integer really, if you do a printf as a %i you get the ASCII value, if you do a %c you get the character. Do %x for hexadecimal. All from the same number between 0 and 255.
I'm quite happy with my "make a weak pin storage program" solution. Maybe it will help people who need a very simple binary file IO example to follow.
$ ls
WeakPin my_pin_code.pin weak_pin.c
$ ./WeakPin
Pin: 45 47 49 32
$ ./WeakPin 8 2
$ Need 4 ints to write a new pin!
$./WeakPin 8 2 99 49
Pin saved.
$ ./WeakPin
Pin: 8 2 99 49
$
$ cat weak_pin.c
// a program to save and read 4-digit pin codes in binary format
#include <stdio.h>
#include <stdlib.h>
#define PIN_FILE "my_pin_code.pin"
typedef struct { unsigned short a, b, c, d; } PinCode;
int main(int argc, const char** argv)
{
if (argc > 1) // create pin
{
if (argc != 5)
{
printf("Need 4 ints to write a new pin!\n");
return -1;
}
unsigned short _a = atoi(argv[1]);
unsigned short _b = atoi(argv[2]);
unsigned short _c = atoi(argv[3]);
unsigned short _d = atoi(argv[4]);
PinCode pc;
pc.a = _a; pc.b = _b; pc.c = _c; pc.d = _d;
FILE *f = fopen(PIN_FILE, "wb"); // create and/or overwrite
if (!f)
{
printf("Error in creating file. Aborting.\n");
return -2;
}
// write one PinCode object pc to the file *f
fwrite(&pc, sizeof(PinCode), 1, f);
fclose(f);
printf("Pin saved.\n");
return 0;
}
// else read existing pin
FILE *f = fopen(PIN_FILE, "rb");
if (!f)
{
printf("Error in reading file. Abort.\n");
return -3;
}
PinCode pc;
fread(&pc, sizeof(PinCode), 1, f);
fclose(f);
printf("Pin: ");
printf("%hu ", pc.a);
printf("%hu ", pc.b);
printf("%hu ", pc.c);
printf("%hu\n", pc.d);
return 0;
}
$
This is an example to read and write binary jjpg or wmv video file.
FILE *fout;
FILE *fin;
Int ch;
char *s;
fin=fopen("D:\\pic.jpg","rb");
if(fin==NULL)
{ printf("\n Unable to open the file ");
exit(1);
}
fout=fopen("D:\\ newpic.jpg","wb");
ch=fgetc(fin);
while (ch!=EOF)
{
s=(char *)ch;
printf("%c",s);
ch=fgetc (fin):
fputc(s,fout);
s++;
}
printf("data read and copied");
fclose(fin);
fclose(fout);
I really struggled to find a way to read a binary file into a byte array in C++ that would output the same hex values I see in a hex editor. After much trial and error, this seems to be the fastest way to do so without extra casts. By default it loads the entire file into memory, but only prints the first 1000 bytes.
string Filename = "BinaryFile.bin";
FILE* pFile;
pFile = fopen(Filename.c_str(), "rb");
fseek(pFile, 0L, SEEK_END);
size_t size = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
uint8_t* ByteArray;
ByteArray = new uint8_t[size];
if (pFile != NULL)
{
int counter = 0;
do {
ByteArray[counter] = fgetc(pFile);
counter++;
} while (counter <= size);
fclose(pFile);
}
for (size_t i = 0; i < 800; i++) {
printf("%02X ", ByteArray[i]);
}
this questions is linked with the question How to write binary data file on C and plot it using Gnuplot by CAMILO HG. I know that the real problem have two parts: 1) Write the binary data file, 2) Plot it using Gnuplot.
The first part has been very clearly answered here, so I do not have something to add.
For the second, the easy way is send the people to the Gnuplot manual, and I sure someone find a good answer, but I do not find it in the web, so I am going to explain one solution (which must be in the real question, but I new in stackoverflow and I can not answer there):
After write your binary data file using fwrite(), you should create a very simple program in C, a reader. The reader only contains the same structure as the writer, but you use fread() instead fwrite(). So it is very ease to generate this program: copy in the reader.c file the writing part of your original code and change write for read (and "wb" for "rb"). In addition, you could include some checks for the data, for example, if the length of the file is correct. And finally, your program need to print the data in the standard output using a printf().
For be clear: your program run like this
$ ./reader data.dat
X_position Y_position (it must be a comment for Gnuplot)*
1.23 2.45
2.54 3.12
5.98 9.52
Okey, with this program, in Gnuplot you only need to pipe the standard output of the reader to the Gnuplot, something like this:
plot '< ./reader data.dat'
This line, run the program reader, and the output is connected with Gnuplot and it plot the data.
*Because Gnuplot is going to read the output of the program, you must know what can Gnuplot read and plot and what can not.
#include <stdio.h>
#include <stdlib.h>
main(int argc, char **argv) //int argc; char **argv;
{
int wd;
FILE *in, *out;
if(argc != 3) {
printf("Input and output file are to be specified\n");
exit(1);
}
in = fopen(argv[1], "rb");
out = fopen(argv[2], "wb");
if(in == NULL || out == NULL) { /* open for write */
printf("Cannot open an input and an output file.\n");
getchar();
exit(0);
}
while(wd = getw(in), !feof(in)) putw(wd, out);
fclose(in);
fclose(out);
}
Today, I read a blog named by "a bug of fread?", I didn't find any reason for it, so I paste it here waiting for any genius.
First, the purpose of the program is to read a file(readme.txt) and print the content, and I test it with Visual Studio 2010.
The content of the readme is :
1234;
abcd;
ABCD;
The hex value of readme is :
31 32 33 34 3b 0d 0a 61 62 63 64 3b 0d 0a 41 42 43 44 3b
Here is the code:
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
int main()
{
FILE *fp = NULL;
int rcnt = 0;
char rbuf[BUF_SIZE];
fp = fopen("readme.txt", "r");
if (NULL == fp)
{
printf("fopen error.\n");
return -1;
}
printf("--------------------------\n");
memset(rbuf, 0, BUF_SIZE);
fseek(fp, 0, SEEK_SET);
rcnt = fread(rbuf, 1, BUF_SIZE, fp);
printf("read cnt = %d\n", rcnt);
printf("%s\n", rbuf);
return 0;
}
Such a simple code, and the expected result is :
--------------------------
read cnt = 17
1234;
abcd;
ABCD;
Total 17 count include 15 characters and 2 '\n'.
But I got the below result:
--------------------------
read cnt = 17
1234;
abcd;
ABCD;D;
PS: If call fopen function with "rb", or if define the macro BUF_SIZE smaller, I got the correct result.
fread() doesn't return a NUL terminated string, but printf("%s") ask for a NUL terminated string.
You have to add a '\0' at the end of the read buffer: rbuf[rcnt] = '\0'.
And remember to read one byte less than the buffer size to leave room for the NUL byte.
I think it's wrong to use fread(), a binary reading API, with a text file. The default mode (if you just say "r") is text.
Note that FILE * I/O in text mode typically does line-termination translation, so that you can pretend that lines end with \n when they might in fact physically end with \r\n (as yours do).
This conversion might introduce confusion somewhere; which is why switching to binary mode makes it work again as no such translation happens in binary mode.