I am trying to read a binary file containing integers in the binary form. I need to use the open() and read() functions rather than fopen() and the like.
I open my file and try to read it, but i get binary symbols in my output.
char buffer[sizeof(int)];
int file1;
int bytesRead;
file1 = open(argv[1], O_RDONLY);
if(file1 == -1)
{
printf("unable to open file\n");
exit(1);
}
while((bytesRead = read(file1, &buffer, sizeof(buffer))))
{
printf("%d\n", buffer);
}
Can anyone point me in the right direction?
Error 1: read(file1, &buffer, sizeof(buffer)
When you use an array, then you need not pass it address to the "read" call.
Correction :
read(file1, buffer, sizeof(buffer);
Error 2 :
while((bytesRead = read(file1, &buffer, sizeof(buffer))))
Correction :
while((bytesRead = read(file1, &buffer, sizeof(buffer))) >= 0)
The while loop will evaluate to true even if the read call fails, since it returns -1 on
failure which means true.
It returns 0 when there's nothing left to read, you can apply a check on that to
indicating that there's nothing more tobe read.
Variables should be declared with the type they are used as:
int buffer;
If you want an int, declare an int. This is an oversimplification, but this way you’re safe against strict-aliasing violations. If only this line is changed, the other code is fine.
The original
char buffer[sizeof(int)];
has the drawback, that it’s impossible to read it as an int without violating strict-aliasing*) (strict-aliasing means, you mustn’t access an object through an lvalue with a wrong type—in short, that is, different from the declared one).
The behaviour of
printf("%d\n", buffer);
is undefined, a value of type char * is passed to printf where an int is expected. (This line is OK if buffer is an int; and it should be declared as an int, since it is read as an int.)
If a char array was really what is intended, the line
while((bytesRead = read(file1, &buffer, sizeof(buffer))))
would be unusual: Arrays decay to pointers when passed to a function, there’s no need to use the address operator &. (But it’s needed if buffer is of type int.)
*) Not entirely impossible, you could type-pun with a union.
Related
I have the following function and I am wondering if there is a way to pass string or char array instead of stdout into it so I can get the printed representation as a string.
void print_Type(Type t, FILE *f)
{
fprintf(f,"stuff ...");
}
print_Type(t, stdout);
I have already tried this:
int SIZE = 100;
char buffer[SIZE];
print_Type(t, buffer);
But this is what I am seeing:
�����
Something like this
FILE* f = fmemopen(buffer, sizeof(buffer), "w");
print_Type(t, f);
fclose(f);
The fmemopen(void *buf, size_t size, const char *mode) function opens a stream. The stream allows I/O to be performed on the string or memory buffer pointed to by buf.
Yes there is sprintf() notice the leading s rather than f.
int SIZE = 100;
char buffer[SIZE];
sprintf(buffer, "stuff %d", 10);
This function prints to a string s rather than a file f. It has exactly the same properties and parameters to fprintf() the only difference is the destination, which must be a char array (either statically allocated as an array or dynamical allocated (usually via malloc)).
Note: This function is dangerous as it does not check the length and can easily overrun the end of the buffer if you are not careful.
If you are using a later version of C (c99). A better function is snprintf this adds the extra buffer length checking.
The problem with fmemopen is that it cannot resize the buffer. fmemopen did exist in Glibc for quite some time, but it was standardized only in POSIX.1-2008. But that revision included another function that handles dynamic memory allocation: open_memstream(3):
char *buffer = NULL;
size_t size = 0;
FILE* f = open_memstream(&buffer, &size);
print_Type(t, f);
fclose(f);
buffer will now point to a null-terminated buffer, with size bytes before the extra null terminator! I.e. you didn't write null bytes, then strlen(buffer) == size.
Thus the only merit of fmemopen is that it can be used to write to a fixed location memory buffer or fixed length, whereas open_memstream should be used everywhere else where the location of the buffer does not matter.
For fmemopen there is yet another undesired feature - the writes may fail when the buffer is being flushed and not before. Since the target is in memory, there is no point in buffering the writes, so it is suggested that if you choose to use fmemopen, Linux manual page fmemopen(3) recommends disabling buffering with setbuf(f, NULL);
I have this fragment
fseek(sp,f_line*fm,SEEK_SET);
fgets(buffer,LEN,(FILE*)sp);
I don't understand this part
(FILE)sp
I try to fill a char array with data from a file.
Apparently, someone thinks they are storing a file pointer in a variable sp that is not of type FILE *, so it is reputed to be necessary to cast the type to FILE *. See the POSIX definition of fgets(), which is meant to be equivalent to the standard C definition of the function.
However, given that the prior line calls fseek() with an uncast sp, and fseek() also expects a FILE *, someone is confused — the person writing the cast is confused.
The cast should be removed from the call to fgets().
Or, possibly but implausibly, the cast should be added to the call to fseek().
One outré possibility is that the user defined void *sp and used that to store the FILE * returned by fopen() or equivalent. Such a decision would be extremely unorthodox, and pointlessly opens up the code to type confusion, but could actually allow the code shown below to compile and run — but the cast is still unnecessary.
/* Abominable code - do not use! */
#include <stdio.h>
int main(void)
{
void *sp = fopen("abuse47.c", "r"); // The abomination!
if (sp != 0)
{
char buffer[256];
fseek(sp, 120, SEEK_SET);
if (fgets(buffer, sizeof(buffer), sp) != 0)
printf("[%s]\n", buffer);
fclose(sp);
}
return 0;
}
so written a small function (part of a larger program) and when i run it and input "GET" it exits with a value of 1. to be honest i'm still grasping the concept of open read and write to stdout but not sure what i've done wrong here.
int input_arg()
{
MainStruct val; //variables are loaded from a config file to this structure
char *getInput;
char *fileInput;
FILE *loadfile;
char buffer[1024];
int n;
int defaultFile = val.def; //success.txt value read when fileparser.c is run
printf("http >> :");
fflush(NULL);
fscanf(stdin,"%s", getInput);
if (getInput == "GET")
{
loadfile = fopen(defaultFile, "r");
if (loadfile == NULL)
{
fprintf(stderr, "error loading default resource: PROGRAM WILL EXIT");
exit(0);
}
while ((n = read(loadfile, buffer, sizeof(buffer))) > 0) //reads file (not sure this should be a while loop)
{
if((write(STDOUT_FILENO, buffer, n)) < 0) //writes to stdout
{
perror("failed to display file to output");
close(loadfile);
exit(1);
}
}
}
}
for compiling purposes the val.def pointer is a string as below
char defaultFile = "success.txt";
unsure of what i am missing here. tried changing the structure pointer to a simple char string to see if it was anything there but didn't actually make any difference. i think the problem is with the while loop...i don't think it should be there, but i have yet to find an example where a while loop ISN'T used in a write to stdout scenario.
thanks
It crashes because you have not allocated any memory for getInput to point at. So the program will crash when it attempts to follow the pointer, which will not point to anything useful.
Either allocate memory dynamically with for example malloc, or replace it with a static buffer.
Also, you may want to look at strcmp for comparing strings. Comparing strings in C with == will not compare the strings lexically, instead it will only compare the pointers pointing at them.
fscanf(stdin,"%s", getInput);
getInput is never initialized or allocated memory.Fix it by allocating memory
getInput = malloc(200);
Your program has serious issues, the most important one is that you are using fopen() with read() and that is wrong.
The read() function takes and int as first parameter, which is a file descriptor tha you can create via the open() function, and not fopen() which returns a FILE * object, so change[1]
FILE *loadFile;
to
int loadFile;
and
loadFile = fopen(defaultFile, "r");
to
loadFile = open(defaultFile, O_RDONLY);
and then to check for failure
if (loadFile == -1) /* it failed to open check errno? perhaps... */
you must enable compiler warnings to prevent this kind of mistake, because the first parameter of read() in your program is of incompatible type.
The fscanf() function expects a valid pointer for each "%s" specifier, you are passing an unintialzed pointer to it, dereferencing it inside of scanf() is undefined behavior.
You need to allocate space for it, something like this should work
char inputBuffer[100];
if (fscanf(stdin, "%99s", inputBuffer) != 1)
thereWasAProblemGettingInput_DoNotUse_inputBuffer_InTheCodeThatFollows();
Note that:
I used inputBuffer as a name for the variable, though this doesn't affect the program execution or compilation at all, the readability matters.
Used "%99s" to prevent buffer overflow.
Checked the value returned by fscanf() to make sure that the inputBuffer has valid data and was properly initialized.
String comparison in c is not like in many other languages, in your code
if (getInput == "GET")
is comparing the addresses of getInput and the string literal "GET", which will not be the same unless you make getInput point to "GET", since you want to compare the contents you need
if (strcmp(inputBuffer, "GET") == 0)
instead, and do not forget to include the string.h header.
[1]Note that loadFile is also a bad choice for a variable name, it feels like a function name, inputFile would be more appropriate.
I'm sorry to bother you with this, but i'm stuck with it for too long already.
I get the following warning on fread: "warning: passing argument 1 of ‘fread’ makes pointer from integer without a cast"
I'm new to C and really like it, but don't get over this.
Thanks in advance.
typedef unsigned char byte;
int main( int argc, char *argv[]){
FILE * filein;
filein = fopen(argv[1], "r" );
int width=10;
int height=10;
byte ** data;
// Allocation
data = (byte **) malloc(height*sizeof(byte *));
for(int i=0;i<height;i++){
data[i]=(byte *) malloc(width*sizeof(byte));
}
for(int i=0;i<height;i++){
for(int j=0;j<width;j++){
fread(data[i][j], sizeof(const char), 1, infile);
}
}
for(int i=0;i<height;i++){
free(data[i]);
}
free(data);
fclose(filein);
return 0;
exit(0);
}
This is only a small piece of the actual program. The task is to read a binary pgm-image, store it in a data-matrix, normalize the values and write them to a new binary pgm-image.
fread() expects the void* pointer to the buffer. You are passing the value stored in data[i][j], not the pointer to the element data[i][j].
Try using the
fread(&data[i][j], sizeof(const char), 1, infile);
By the way, .pgm file format (if this is it) has a header and it is not sufficient to read only the width*height characters. The pixel values are also separated by spaces, so a little parsing is required. Also keep in mind that the end-of-line symbols also take space (.pgm cannot have more than 70 characters on one line)
The type of data[i][j] is byte. That is not a pointer. What you really want is to read to &data[i][j], if you're reading one byte at a time.
To read a single char, you can do
int c; // not char, because it must be able to hold EOF
c = getc(infile);
if( c == EOF ){
// do something about error or premature EOF
}
data[i][j] = c;
This is more verbose mostly because of the error checking that your code doesn't do.
I'm working through the curve to learn C and I don't understand why compiler is reporting this this warning.
I have a char* that is declared in global space (outside of any function). I want to read a file descriptor and return it's contents to the calling code.
At the top of the file I have the buffer declared:
char * buffer[256];
And this is the function that returns the char*
char * readMessage()
{
int n;
bzero(buffer,256);
n = read(sockfd,buffer,255);
if(n < 0)
error("Error reading from the socket");
return buffer;
}
How can the return type be of an incompatible type? Thanks!
You wrote:
char * buffer[256];
That is, an array of 256 char pointers.
It seems to me what you really want is:
char buffer[256];
Or, an array of 256 characters (also known as a 'string' :-))
Off-topic, but related to your code: This is not a good way to read from a socket. Chances are, read() will at some point return fewer characters than you expect. You should have some mechanism in place to communicate the length of your messages, and read from the socket in a loop, buffering characters until you get a complete message. You should also handle the case where read() returns zero (likely disconnect) or when it fails and sets errno to EINTR (meaning you got a signal while inside read and you should try again).
char *buffer[256] declares an array of 256 pointers-to-char. You probably want char buffer[256].