I am doing a coding task in the C language, I go well until the part of reading the symbol and assign the corresponding code according to a table. I must concatenate several codes until they reach 32 bits in length, to accomplish this I must write them in a file.
This method of writing to file is giving me a lot of problems, I'm trying to do it with the fputc() function.
I can not change the declaration of the function because they request it for the homework.
I create a mask to be able to write the integer by bytes because they also suggest that the teachers of the course.
The program with that code works but when I see the file with a binary viewer it only prints zero.
Any idea of what I'm doing wrong?
Thanks!
void write_int(FILE* fp, unsigned int buffer, int nbytes){
if ( (nbytes <= sizeof(int)) && (nbytes>=0) ){
unsigned int aux;
int i;
for (i=4; i>(4-nbytes) ; i--){
aux = buffer & new_mask( ((i*8)-1),((i-1)*8));
fputc(aux,fp)
}
fputc('\n',fp);
}else{
printf("nbytes out of range");
}
}
fputc is used to write one ASCII-character into a file.
int fputc(int, FILE*) //this int is converted to unsigned before going to the file(your bits are probably being messed up here)
1- solution: Open this file in binary mode and write using fwrite
fp = fopen("filename", "wb+");
fwrite(buffer, 4, 1, fp);
*since integers on most computers have 32bits(4bytes) this should write your whole 32 bits at once in a binary file
2- solution: Assuming that you can't open the file in binary mode inside this function... you could simply write 4chars usgin fprintf.
int fprintf(FILE*, format, ....);
*note: it's hard to help more than this, because it's not clear what is nature of these symbols.
ex: binary stream, integer number, ascii, utf, etc
Related
I've been trying to write the contents of an integer array to a file in C. I've been using the code below to do so.
int etData [600];
int i;
int size = sizeof(char);
for (i=0; i<600; i++)
{
etData[i] = analog_et(5);
}
FILE *f = fopen("/home/root/Documents/KISS/Default User/Launch Code/data/data", "w");
fwrite(etData, size, sizeof(etData), f);
fclose(f);
analog_et is a function that returns an integer value from a sensor. Whenever I run this code, a mess of ASCII characters is written to the file. I believe this is to blame on the fact that I am passing fwrite an element size sizeof(char) - however, whenever I attempt to pass a value larger than one byte, nothing is written to the file, and fwrite fails to return a non-zero value.
I've looked for a function in stdio that would be better suited to this purpose but can't find one. Any suggestions on how to fix this issue? Thanks!
If you want a textual representation of your data (in that case the file can be opened with a text editor), you cannot user fwrite but you need to use fprintf. Latter does basically is the same thing as printf, but instead of being displayed, the data is written into a text file.
You probably want this:
...
FILE *f = fopen("/home/root/Documents/KISS/Default User/Launch Code/data/data", "w");
for (i=0; i<600; i++)
{
fprintf("%d\n", etData[i]);
}
...
I have an embedded board (beagleboard-xm) that runs ubuntu 12.04, I would like to read one GPIO input if it is logic 1 or 0. How can I implement cat /sys/class/gpio/gpio139/value in C? (value file stores 0 or 1)
I open the file by:
FILE *fp;
fp = fopen("/sys/class/gpio/gpio139/value", "rb");
what do I need to do next?
If you want to read one character, try this:
int value = fgetc(fp);
/* error checking */
value = value - '0';
You can read one byte, or until eof:
char buffer[32]; // Very long number!
if (NULL == (fp = fopen(FILENAME, "rb")))
{
// TODO: return a suitable error/perror
return -1;
}
bytesread = fread(buffer, sizeof(char), sizeof(buffer)-1, fp);
fclose(fp);
if (!bytesread)
{
// Nothing at all was read
// TODO: return error
return -2;
}
// This is in case you want the byte interpreted from ASCII
// otherwise you'd just return buffer[0], or (*(DATATYPE *)buffer)[0].
buffer[bytesread] = 0x0;
return atol(buffer);
This code is actually not that general, in that many hardware devices will implement a blocking data channel - that is, if you try to read more data than it's there, the fread will block until data becomes available. In such a case, just dimension the buffer to the maximum number of bytes you need, plus one.
The plus one, and the corresponding -1 in the fread, are only there for the case in which the data you read is rendered as ASCII, i.e., "128" is three ASCII bytes "1", "2", "8" and maybe even a carriage return, instead of a binary 0x80. In this case, the buffer is zero-terminated to make it a C string on which atol may operate to retrieve a decimal number.
If what is needed is a binary value, then no such conversion is needed, and one can read the full buffer without adjustments, avoid setting the last plus one byte to zero, and just return a cast value from the buffer; or buffer[0] if only one byte is needed.
After attempting to open the file, you check that the fopen() succeeded.
Then you can use any of the stdio functions to read the data:
getc()
fgetc()
fgets()
fread()
and probably others too. You might be looking at the scanf() family, but most probably won't be using them, for example. Which is most appropriate depends on the data that is read; is it text or is it binary. If it is a single character, then getc(); if it is text and line-oriented, maybe fgets(); if binary, probably fread().
If you have access to your Linux headers, than I would recommend you to access GPIO using Linux API.
Include this in your file:
#include <linux/gpio.h>
Now you have access to functions like:
int gpio_is_valid(int number);
int gpio_get_value(unsigned gpio);
void gpio_set_value(unsigned gpio, int value);
In your case you can just write this:
int io_ret = -1;
if (gpio_is_valid(139))
io_ret = gpio_get_value(139);
i think it will be better if you used:
system("echo /sys/class/gpio/gpio139/value >> temp.txt ");
after that it is easy you can just extract the value from temp.txt which will be either 0 or 1
Here i am using two different functions for calculating CRC16 for any type of file (.txt,.tar,.tar.gz,.bin,.scr,.sh etc) and different size also varies from 1 KB to 5 GB.
I want to achieve this
`cross platform
less time consuming
Have to work proper for any type of file and any size`
i got same value of CRC in both functions. but any one can tell me which one is more better to calculate CRC16 for any type of file with any size on different different platform.
Here we have to consider 0 to 255 all type characters.
Can any body please suggest me which one is good in my requirements.
Code of both functions :
First one which has int datatype in readChar here i am using int readChar
int CRC16_int(const char* filePath) {
//Declare variable to store CRC result.
unsigned short result;
//Declare loop variables.
int intInnerLoopIndex;
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.
int 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) {
//printf("charcater is %c\n",readChar);
//printf("charcater is %c and int is %d \n",readChar,readChar);
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("\nCRC data length in file: %d", chCnt);
//This is final CRC value for provided message.
return (result);
}
Second one is unsigned char datatype of readChar Here i am using unsigned char readChar
int CRC16_unchar(const char* filePath) {
unsigned int filesize;
//Declare variable to store CRC result.
unsigned short result;
//Declare loop variables.
unsigned int intOuterLoopIndex, intInnerLoopIndex;
result = 0xffff; //initialize result variable to perform CRC checksum calculation.
FILE *readFile;
//Use to read character from file.
//The problem is if you read a byte from a file with the hex value (for example) 0xfe,
//then the char value will be -2 while the unsigned char value will be 254.
//This will significantly affect your CRC
unsigned 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);
}
fseek(readFile, 0, SEEK_END); // seek to end of file
filesize = ftell(readFile); // get current file pointer
fseek(readFile, 0, SEEK_SET); // seek back to beginning of file
/*
Here reading file and store into variable.
*/
int chCnt = 0;
for (intOuterLoopIndex = 0; intOuterLoopIndex < filesize; intOuterLoopIndex++) {
readChar = getc(readFile);
printf("charcater is %c and int is %d\n",readChar,readChar);
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
} else {
result = result >> 1; //Perform bit shifting.
}
}
chCnt++;
}
printf("\nCRC data length in file: %d", chCnt);
return (result);
}
Please Help me to figure out this problem
Thanks
First things first. Don't do file reading (or whatever the source is) and CRC calculating in the same function. This is bad design. File reading is typically not completely platform independent (although POSIX is your best friend), but CRC calculation can be done very platform independently. Also you might want to reuse your CRC algorithm for other kind of data sources which aren't accessed with fopen().
To give you a hint, the CRC function I always drop in to my projects has this prototype:
uint16_t Crc16(const uint8_t* buffer, size_t size,
uint16_t polynomial, uint16_t crc);
You don't have to call the function once and feed it the complete contents of the file. Instead you can loop through the file in blocks and call the function for each block. The polynomial argument in your case is 0xA001 (which is BTW a polynomial in 'reversed' form), and the crc argument is set to 0xFFFF the first time. Each subsequent time you call the function you pass the previous return value of the function to the crc argument.
In your second code frament (CRC16_unchar) you first determine the filesize and then read that number of bytes. Don't do that, it unnecessary limits you to handle files of maximum 4GB (in the most cases). Just reading until EOF is cleaner IMHO.
Furthermore I see that you are struggling with signed/unsigned bytes. Do know that
printf doesn't know if you pass an signed or unsigned integer. You tell printf with '%d' or '%u' how to interpret the integer.
Even in C itself there is hardly a difference between a signed and unsigned integer. C won't magically change the value of 255 to -1 if you do int8_t x = 255.
See this anser for more details about when C uses the signedness of an integer: When does the signedness of an integer really matter?. Rule of thumb: Just always use uint8_t for handling raw bytes.
So both functions are fine regarding signedness/integer size.
EDIT: As other users indicated in their answers, read the file in block instead per-byte:
uint16_t CRC16_int(const char* filePath) {
FILE *readFile;
const uint8_t buf[1024];
size_t len;
uint16_t result = 0xffff;;
/* Open a file for reading. */
readFile = fopen(filePath, "rb");
if (readFile == NULL) {
exit(1);
}
/* Read until EOF. */
while ( (len = fread(buf, sizeof(buf), 1, readFile)) > 0 ) {
result = Crc16(buf, len, 0xA001, result);
}
/* readFile could be in error state, check it with ferror() or feof() functions. */
return result;
}
Also you should alter you function prototype to make it possible to return an error, e.g.:
// Return true when successful, false on error. CRC is stored in result.
bool CRC16_int(const char* filePath, uint16_t *result)
You want to read and write 8-bit bytes using unsigned char instead of plain char because char can be either signed or unsigned and that's up to the compiler (allowed by the C standard). So, the value you get from getc() should be converted to unsigned char prior to being used in the CRC calculations. You could also fread() into an unsigned char. If you work with signed chars, sign extension of chars into ints will likely break your CRC calculations.
Also, per the C standard fseek(FilePtr, 0, SEEK_END) has undefined behavior for binary streams and binary streams need not meaningfully support SEEK_END in fseek(). In practice, though, this usually works as we want.
Another thing you should consider is checking for I/O errors. Your code is broken in this respect.
The datatype you do the calculation with should, in my opinion, not be the same that you read from the file. Doing one function call into the runtime library to read a single byte is simply not efficient. You should probably read on the order of 2-4 KB at a time, and then iterate over each returned "chunk" in whatever manner you choose.
There's also absolutely no point in reading in the size of the file in advance, you should simply read until reading returns less data than expected, in which case you can inspect feof() and ferror() to figure out what to do, typically just stop since you're done. See the fread() manual page.
I'm trying to read a BMP image (greyscales) with C, save values into an array, and convert this array to a string with values separated with a comma.
My program worked well under Windows 7 64-bit, but I had to move to Windows XP 32-bit because of library compatibility problems.
I have 1,750 images to read, and I want to store all of them in a single string.
When I launch my program it goes fine until the 509:th image, then I get a Segmentation Fault caused by fread(). Here's my code:
int i=0,j,k,num,len,length,l;
unsigned char *Buffer;
FILE *fp;
char *string,*finalstring;
char *query;
char tmp2[5],tmp[3];
query = (char *)malloc(sizeof(char)*200000000);
string = (char *)malloc(sizeof(char)*101376);
Buffer = (unsigned char *)malloc(sizeof(unsigned char)*26368);
BITMAPFILEHEADER bMapFileHeader;
BITMAPINFOHEADER bMapInfoHeader;
length = 0;
for (k =1;k<1751;k++)
{
strcpy(link,"imagepath");
//here just indexing the images from 0000 to 1750
sprintf(tmp2,"%.4d",k);
strcat(link,tmp2);
strcat(link,".bmp");
fp = fopen(link, "rb");
num = fread(&bMapFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
num = fread(&bMapInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);
//seek beginning of data in bitmap
fseek(fp,54,SEEK_SET);
//read in bitmap file to data
fread(Buffer,26368,1,fp);
l=0;
for(i=1024;i<26368;i++)
{
itoa(Buffer[i],tmp,10);
len = strlen(tmp);
memcpy(string+l,tmp,len);
memcpy(string+l+len,",",1);
l = l+len+1;
}
memcpy(query,"",1);
memcpy(string,"",1);
printf("%i\n",k);
}
Thanks
Make it tmp[4]; for three digits and the terminating 0.
Also: where is the fclose? I suspect that you're running out of file handles.
Check, whether fp != 0.
Where did you get 101376 from? Each of your bytes take up at most 5 characters as a decimal number with comma (e.g. -127,), 5*26368 is 131840.
Get rid of the casts in malloc calls. And #include <stdlib.h>.
What's the output of this program, in both the 64-bit and 32-bit systems you're using?
#include <stdio.h>
int main(void) {
printf("sizeof (int) is %d\n", (int)(sizeof (int)));
printf("sizeof (int*) is %d\n", (int)(sizeof (int*)));
return 0;
}
Run your program in the debugger.
Set a breakpoint at the call to
fread -- make it conditional on
k==507 (this will stop it when you
expect the fread to be successful).
When the program hits the
breakpoint, examine the variables
and check what is about to be passed
to fread. The first one or two times
you hit the breakpoint, the values
will be good.
Then on the 509th time, you will
probably see bogus values being passed
to fread. Figure out where those
bogus values are coming from --
possibly set a conditional
breakpoint on the variable being set
to whatever the bogus value is.
Here is the snippet of code
typedef struct
{
double testA;
double testB[500];
bool isProcessed;
} MYSTURCT;
I have a binary file which is written with multiple structs of type "myStruct".
Now, in another function, I m trying to read the file and update in the middle.
void test()
{
FILE* fp = fopen (testFile, "r+")
MYSTURCT* myPtr = malloc (sizeof (MYSTRUCT));
while ( fread (myPtr,sizeof(MYSTRUCT),1,fp) )
{
if (!myPtr->isProcessed)
{
//update some thing int he struct
myPtr->testA = 100.00;
fseek (fp, -sizeof(MYSTRUCT), SEEK_CUR);
fwrite (myPtr,sizeof(MYSTRUCT), 1,fp);
}
}
}
Once I find something unprocessed, I update the struct in the memory, then try to
write the struct to the disk. (first by seeking the CURR - sizeof(struct)) position
and then fwriting the struct to disk.
Whats happening in my application is after doing the fseek, my
fp->_ptr is getting messed up and it looses the track of position in my stream.
Is there anything wrong that I am doing here?
-sizeof(STRUCT) is potentially dangerous. sizeof(STRUCT) is an unsigned type, and if it is as least as wide as an int it's promoted type (the type of the -sizeof(STRUCT) expression) will also be unsigned and have a value of about UINT_MAX - sizeof(STRUCT) + 1 or possibly ULONG_MAX - sizeof(STRUCT)+ 1.
If you're unlucky (e.g. 32 bit size_t, 64 bit long) its UINT_MAX - sizeof(STRUCT) + 1 and a long int may be able to hold this large postive value and the seek won't do what you want it to do.
You could consider doing a position save and restore:
fpos_t pos;
if (fgetpos(fp, &pos) != 0)
{
/* position save failed */
return;
}
/* read struct */
if (fsetpos(fp, &pos) != 0)
{
/* position restore failed */
return;
}
/* write struct */
fgetpos and fsetpos use a fpos_t so can potentially work with very large files in scenarios where fseek and ftell won't.
The fopen manpage says:
Reads and writes may be intermixed on
read/write streams in any order.
Note that ANSI C requires that a file positioning function
intervene
between output and input, unless an input operation encounters
end-of-
file. (If this condition is not met, then a read is allowed to
return
the result of writes other than the most recent.) Therefore it is
good
practice (and indeed sometimes necessary under Linux)
to put an
fseek(3) or fgetpos(3) operation between write and read
operations on
such a stream. This operation may be an apparent
no-op (as in
fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect.
So you might try putting the dummy fseek in right after you fwrite.
You malloc sizeof (MYSTRUCT) bytes to myPtr, but myPtr is of type MYSTURCT.
I don't think that's your problem, though.
Apparently there's nothing wrong with your code; try to add some error-checking ...
void test(){
FILE* fp = fopen (testFile, "r+"); /* missing semicolon */
MYSTURCT* myPtr = malloc (sizeof *myPtr);
while ( fread (myPtr,sizeof *myPtr,1,fp) == 1) /* error checking */
{
if (!myPtr->isProcessed)
{
//update some thing int he struct
myPtr->testA = 100.00;
if (fseek (fp, -sizeof *myPtr, SEEK_CUR) == -1)
{
perror("fseek");
}
if (fwrite (myPtr,sizeof *myPtr, 1,fp) != 1)
{
perror("fwrite");
}
}
}
}
And the fopen should be in binary mode, even if you're on Linux (where it really doesn't matter). On Windows a sequence of 0x0D 0x0A in the middle of one of those doubles will get converted to 0x0D and mess everything up.
Try fflush after the last fwrite(). Then Try making a new test file using your current structure. It could be that you changed your structure and your current test file has an older invalid byte order.
I tried your sample code, and it seems to work fine to me (though I am doing it in C - I substituted a "char" for your "boolean")
For debugging, how do you know that the fp is getting corrupted? It is unusual to look at the members of the FILE struct. Each time you do an fseek(), fread() or fwrite(), what is your output when you invoke ftell()?
if you wanted to write to the file you should use "w+b" not "r+" otherwise fwrite would fail and return the error code instead. (I think).