Confusion in file Verification with CRC16 in C - c

Here i want to know the how can i implement calculate CRC16 for Any type of file,
Here i have idea about CRC16 and its code logic.
here i made one function which take file path as a input and find out CRC value of this. here i pass file name in this function and this functions calculates CRC value of this file. but i want to calculate all types of files like .tar,.tar.gz,.txt,.bin,.scr etc.
so here i open this all files and "rb" mode and take one by one character and find out CRC value
its right way? may be i missing something in this. its works fine for .txt and all other files but it will create problems in .tar, .tar.gz type files. Because here i have one file which is 890 MB and its name is file.tar.gz and its take 203 Microseconds and I have other file which is 382 MB and its name is file2.tar its take 6097850.000000 Microseconds its unbelievable for me hows its possible?
My question are these
1 Some thing problem in my CRC code ?
2 Problem in reading file data style, may be i am reading file data in wrong manner for .tar.gz.
Here is my code :
int CRC16(const char* filePath) {
//Declare variable to store CRC result.
unsigned short result;
//Declare loop variables.
int intOuterLoopIndex, intInnerLoopIndex, nLen;
result = 0xffff; //initialize result variable to perform CRC checksum calculation.
//Store message which read from file.
//char content[2000000];
//Create file pointer to open and read file.
FILE *readFile;
//Use to read character from file.
char readChar;
//open a file for Reading
readFile = fopen(filePath, "rb");
//Checking file is able to open or exists.
if (!readFile) {
fputs("Unable to open file %s", stderr);
}
/*
Here reading file and store into variable.
*/
int chCnt = 0;
while ((readChar = getc(readFile)) != EOF) {
result ^= (short) (readChar);
for (intInnerLoopIndex = 0; intInnerLoopIndex < 8; intInnerLoopIndex++) {
if ((result & 0x0001) == 0x0001) {
result = result >> 1; //Perform bit shifting.
result = result ^ 0xa001; //Perform XOR operation on result.
} else {
result = result >> 1; //Perform bit shifting.
}
}
//content[chCnt] = readChar;
chCnt++;
}
printf("CRC data length in file: %d", chCnt);
return (result);
}

char readChar; is wrong, it needs to be int readChar;
getc() returns an int, so it can signal EOF to you. EOF is likely the value -1
If you convert the return value to a char, and read a byte with the value 255, 255 will be interpreted as -1, and you stop reading at the first byte that has the value 255.

This code is wrong in different points:
if (!readFile) {
fputs("Unable to open file %s", stderr);
}
If the file opening fails you don't return but continue! And the puts is wrong also, you don't specify the file name.
Also, getc() returns an integer, but you put it in a char and it may end just when it finds an EOF character! Don't ignore compiler warnings...
I would download a small CRC calculator program, so that you can test if your code is working properly.

Related

y with umlaut in file

I'm working on an example problem where I have to reverse the text in a text file using fseek() and ftell(). I was successful, but printing the same output to a file, I had some weird results.
The text file I input was the following:
redivider
racecar
kayak
civic
level
refer
These are all palindromes
The result in the command line works great. In the text file that I create however, I get the following:
ÿsemordnilap lla era esehTT
referr
levell
civicc
kayakk
racecarr
redivide
I am aware from the answer to this question says that this corresponds to the text file version of EOF in C. I'm just confused as to why the command line and text file outputs are different.
#include <stdio.h>
#include <stdlib.h>
/**********************************
This program is designed to read in a text file and then reverse the order
of the text.
The reversed text then gets output to a new file.
The new file is then opened and read.
**********************************/
int main()
{
//Open our files and check for NULL
FILE *fp = NULL;
fp = fopen("mainText.txt","r");
if (!fp)
return -1;
FILE *fnew = NULL;
fnew = fopen("reversedText.txt","w+");
if (!fnew)
return -2;
//Go to the end of the file so we can reverse it
int i = 1;
fseek(fp, 0, SEEK_END);
int endNum = ftell(fp);
while(i < endNum+1)
{
fseek(fp,-i,SEEK_END);
printf("%c",fgetc(fp));
fputc(fgetc(fp),fnew);
i++;
}
fclose(fp);
fclose(fnew);
fp = NULL;
fnew = NULL;
return 0;
}
No errors, I just want identical outputs.
The outputs are different because your loop reads two characters from fp per iteration.
For example, in the first iteration i is 1 and so fseek sets the current file position of fp just before the last byte:
...
These are all palindromes
^
Then printf("%c",fgetc(fp)); reads a byte (s) and prints it to the console. Having read the s, the file position is now
...
These are all palindromes
^
i.e. we're at the end of the file.
Then fputc(fgetc(fp),fnew); attempts to read another byte from fp. This fails and fgetc returns EOF (a negative value, usually -1) instead. However, your code is not prepared for this and blindly treats -1 as a character code. Converted to a byte, -1 corresponds to 255, which is the character code for ÿ in the ISO-8859-1 encoding. This byte is written to your file.
In the next iteration of the loop we seek back to the e:
...
These are all palindromes
^
Again the loop reads two characters: e is written to the console, and s is written to the file.
This continues backwards until we reach the beginning of the input file:
redivider
^
Yet again the loop reads two characters: r is written to the console, and e is written to the file.
This ends the loop. The end result is that your output file contains one character that doesn't exist (from the attempt to read past the end of the input file) and never sees the first character.
The fix is to only call fgetc once per loop:
while(i < endNum+1)
{
fseek(fp,-i,SEEK_END);
int c = fgetc(fp);
if (c == EOF) {
perror("error reading from mainText.txt");
exit(EXIT_FAILURE);
}
printf("%c", c);
fputc(c, fnew);
i++;
}
In addition to #melpomene correction about using only 1 fgetc() per loops, other issues exist.
fseek(questionable_offset)
fopen("mainText.txt","r"); opens the file in text mode and not binary mode. Thus the using fseek(various_values) as a valid offset into the file is prone to troubles. Usually not a problem in *nix systems.
I do not have a simple alternative.
ftell() return type
ftell() return long. Use long instead of int i, endNum. (Not a concern with small files)
Check return values
ftell() and fseek() can fail. Test for error returns.

C program prepends, when it should append

Trying to write a program in C, which I've never used before, to convert hexadecimal to binary as a string and write it to a file, The only problem is that it prepends to the output file when I want it to append.
This occurs for both fprintf() and fputs().
This is the append code:
while(fgets(line,1024,inputFile)){
lineLen = strlen(line);
binary = hexToBin(line, lineLen);
printf("Binary: %s\n", binary);
// output file does not exist
FILE *writeFile = fopen(argv[2], "a");
if (writeFile == NULL) {
fprintf(stderr, "write file not found: %s\n", strerror(errno));
exit(1);
}
printf("appending binary to file\n");
fprintf(writeFile,"%s\n",binary);
printf("appended\n");
}
This is the hexToBin function:
char* hexToBin(char hex[], size_t len){
// convert hexadecimal to binary
char *binString = (char*)malloc(sizeof(char)*4*len);
for (int i=0;i<len;i++){
char *binNum = hexToBinHelp(hex[i]);
strcat(binString,binNum);
free(binNum);
}
return binString;
}
hexToBinHelp returns the hexadecimal character as a char* of it's binary representation (binNum=[0][0][0][0] for example). It's really long so I'd rather not put it here, but can if it would help.
When input file is:
000a
a000
Output file is:
1010000000000000
0000000000001010
Thanks
Your loop is calling fopen() every iteration, and never closing or flushing this file stream. Writes are buffered, waiting for the buffer to fill or be flushed or the file to be closed; so the next time you call fopen() you get the same pointer as the first time.
You're lucky it's not crashing. :) Do not call fopen() repeatedly. Call it once outside the loop, inside use or move the pointer over, and back outside call fclose().

After two successful read fgetc() is not working when used with fseek()

I am trying to encrypt(simple bit manuplation algorithm) a file, for that I created three different version
create new file in the process of encryption or decryption and deletes the old one and renames it
encryption or decryption happens on the same file, using two different File *, one opening the file in rb and another opening the same file in rb+.
encryption or decryption happens on the same file, only one FILE* is used, file opened in rb+ mode.
First two versions works as expected they don't use fseek(), but I am encountering problem in version3
code for v3:
FILE *inputFile= NULL,*outputFile = NULL;
char *inName = "file.txt",*outName;
/* I am using same source file for all three version controlled by #if, so the following assignment is necessary*/
outName = inName;
inputFile = fopen(inName,"rb+");
if(inputFile == NULL)
{
perror(inName);
exit(EXIT_FAILURE);
}
/* I am using same source file for all three version controlled by #if, so the following assignment is necessary*/
outputFile = inputFile;
long int currentLocation;
unsigned char targetChar;
int intChar;
long int offset,temp;
while(currentLocation = ftell(inputFile),(intChar = fgetc(inputFile))!= EOF)
{
targetChar = intChar;
/*#if encryption
encrypt(&targetChar);
#else
decrypt(&targetChar);
#endif // encryption*/
/* going back in the file to the starting position of currently read character*/
temp = currentLocation;
currentLocation = ftell(inputFile);
offset = temp - currentLocation; // the offset is always -1 throughout the program(gdb)
if(fseek(inputFile,offset,SEEK_CUR)==-1)
{
perror(outName);
exit(EXIT_FAILURE);
}
// writing the encrypted or decrpted character to the file
if(fputc(targetChar,outputFile) == EOF)
{
perror(outName);
exit(EXIT_FAILURE);
}
}
fclose(inputFile);
fclose(outputFile);
for the first two character fgetc() is working properly the its is not reading at all, meanwhile the currentLocation is steadily increment.
if the file has following content
Hello world !!
output is
Heelo world !!
or
Heeeeeeeeeeeeeeeeeeeeeeeee ...
the number of e depends on how long the program runs, its an infinite loop.
I am using fseek() to move backwards , does this clear EOF(causing the infinite loop condition) even though I am doing only backward fseek() ? and I checked in debugger the fgetc() is not reading more than two characters but the currentLocation is moving in the increment of 1, why fgetc() is not reading more than two characters?
if(fputc(targetChar,outputFile) == EOF)
{
perror(outName);
exit(EXIT_FAILURE);
}
fflush(outputFile);//need flush
}
fclose(inputFile);
//fclose(outputFile);//double close!

How to write an array to file in C

I have a 2 dimensional matrix:
char clientdata[12][128];
What is the best way to write the contents to a file? I need to constantly update this text file so on every write the previous data in the file is cleared.
Since the size of the data is fixed, one simple way of writing this entire array into a file is using the binary writing mode:
FILE *f = fopen("client.data", "wb");
fwrite(clientdata, sizeof(char), sizeof(clientdata), f);
fclose(f);
This writes out the whole 2D array at once, writing over the content of the file that has been there previously.
I would rather add a test to make it robust !
The fclose() is done in either cases otherwise the file system will free the file descriptor
int written = 0;
FILE *f = fopen("client.data", "wb");
written = fwrite(clientdata, sizeof(char), sizeof(clientdata), f);
if (written == 0) {
printf("Error during writing to file !");
}
fclose(f);
How incredibly simple this issue turned out to be...
The example given above handle characters, this is how to handle an array of integers...
/* define array, counter, and file name, and open the file */
int unsigned n, prime[1000000];
FILE *fp;
fp=fopen("/Users/Robert/Prime/Data100","w");
prime[0] = 1; /* fist prime is One, a given, so set it */
/* do Prime calculation here and store each new prime found in the array */
prime[pn] = n;
/* when search for primes is complete write the entire array to file */
fwrite(prime,sizeof(prime),1,fp); /* Write to File */
/* To verify data has been properly written to file... */
fread(prime,sizeof(prime),1,fp); /* read the entire file into the array */
printf("Prime extracted from file Data100: %10d \n",prime[78485]); /* verify data written */
/* in this example, the 78,485th prime found, value 999,773. */
For anyone else looking for guidance on C programming, this site is excellent...
Refer: [https://overiq.com/c-programming/101/fwrite-function-in-c/

Read and write to binary files in C?

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);
}

Resources