C Read then Write - c

After we do:
int readStat = read(fd, buf, sizeof(buf));
Why should the following be:
int status = write(socket_num, buf, readStat);
instead of
int status = write(socket_num, buf, sizeof(buf));
?
So instead of passing in the size of buf, like the man page instructs, why do we pass in the return value of read?!

read returns the number of bytes actually read, keeping in mind you could have a file 500 bytes long, request to read 500 bytes, but only get 200 returned. So you should always loop with read till end of file is returned. This is especially the case with TCP/IP reading, since your pulling from a buffer.
In actuality you probably will always get the amount of bytes you request from a file if there is enough, however this technically is not always true.
But take for example if you had a 32 byte file, and you had a 500 byte buffer. You would only read in 32 bytes, so the other 500 bytes would be garbage. Now when you write your new file, its 500 bytes long, instead of 32.

Related

Using fread to read in 16 byte blocks

I am writing some code that is supposed to read in blocks of 16 bytes at a time from an input file. I am using fread to do this however I run into problems when I get to the last few bytes of the file.
size_t bytesread=1;
while(bytesread > 0){
bytesread = fread(buffer,16,1,inputfile);
buffer[16]='\0';
fprintf("Read in line: "%s"\n,buffer);
}
Say for example my text file is "This is a testfile. Here are some words".
It would print out
Read in line: "This is a testfi"
Read in line: "le. Here are som"
Read in line: "e words
are som"
I can't figure out why it adds on the extra characters when reading in the last line. I understand that I am reading in a block of 16 bytes but how would I deal with the last block where I only want to read in the last 7 bytes?
fread(buffer,16,1,inputfile); attempts to read one block of 16 bytes. If it fails, fread returns zero, indicating that zero complete blocks were read.
You do not want this; you want to know how many characters were read. So use this code, which attempts to read 16 blocks of one byte each:
bytesread = fread(buffer, 1, 16, inputfile);
After this code, bytesread contains the number of bytes read. You can use this to put an end-of-string marker after the last byte read:
buffer[bytesread] = '\0';
Then printf("Read in line: \"%s\"\n", buffer); will print the bytes just read and no more.

Is there a limitation of bytes to be read with fread()

I'm trying to read data from a file into a buffer. The data in file is of 900K bytes. (seek to end of file and ftell()). Allocated the buffer in which the data is to be read of size 900K + 1 (to null terminate). My question is that fread() returns 900K but the I see the strlen(buffer) it shows lesser value and in the buffer at the last I can see something like ".....(truncated)". Why is this behavior? Is there a limit with fread() beyond which we cannot read into buffer and it will truncate it. Also why the return value of fread() says 900K even though actually it has read even less.?
strlen does something along these lines:
int strlen(char *str)
{
int len = 0;
while(*str++) len++;
return len;
}
If your file contains binary data (or if it's a text file with a UTF encoding and unused upper bytes) strlen is going to stop at the first 0x00 byte it encounters and return how many bytes into the file that was encountered. If you read a text file in a single-byte encoding like ANSI there won't be a null terminator and calling strlen will invoke undefined behavior.
If you want to determine how many bytes that fread successfully read out of the file, check its return value.1
If you want to determine the file size before reading a file, do this:
size_t len;
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
len will contain the file's size in bytes.
1: Assuming you called fread with parameter 2 set to 1 byte per element and didn't try to read more bytes than are actually in the file.
Your main question has already been answered, though it's worth notice that strlen is not designed to measure the size of an array but a NULL-terminated string. It probably prints a lower value because strlen returns the number of characters that appear before a null-char, so if you have nullchars ('\0') through your data, strlen will stop as soon as it finds one of them.
You should trust fread 's return value.
EDIT: as a note, fread MAY read less bytes than requested, and it can be caused by an error or an end of file. You can check it with ferror and feof, respectively.

sending data using send() function in linux

I read the documentation regarding send() function, when it was said that the third parameter (len) is "The length, in bytes, of the data in buffer pointed to by the buf parameter".
I can't seem to understand if it sends the number of bytes I pass, or I nedd to pass the size of the buffer and it sends all the data included there.
Exmaple:
#define X 256
// main :
char test[X] = {0};
memcpy(test, "hello", 6);
send(sockfd, test, 6, 0)
send(sockfd, test, 256,0)
// will the first opetion send only hello? or hello000000....?
Thanks!
The send function sends precisely the number of bytes you tell it to (assuming it's not interrupted and doesn't otherwise fail). The number of bytes you need to send is determined by the protocol you are implementing. For example, if the protocol says you should send "FOO\r\n", then you need to send 5 bytes. If the protocol specifies that integers are represented as 4 bytes in network byte order and you're sending an integer, the buffer should contain an integer in network byte order and you should send 4 bytes. The size of the buffer doesn't matter to send.
As a complement to David Schwartz proper answer:
Depending on if the socket is non-blocking,or not, it is NOT guaranteed that a single send will actually send all data. You must check return value and might have to call send again (with correct buffer offsets).
For instance if you want to send 10 bytes of data (len=10), you call send(sock, buf, len, 0). However lets say it only manages to send 5 bytes, then send(..) will return 5, meaning that you will have to call it again later like send(sock, (buf + 5), (len - 5), 0). Meaning, skip first five bytes in buffer, they're already sent, and withdraw five bytes from the total number of bytes (len) we want to send.
(Note that I used parenthesis to make it easier to read only, and it assumes that buf is a pointer to 1 byte type.)

How to send() an image by saving it in char string in ANSI C? Problem with casting

I'm writing my own server in ANSI C (on Linux) and I've got one problem with sending images to a web browser. I'm using the function "send()" to send it and it required a char *. So I was reading a file char by char (using fgetc), I used fread and fgets, but everything had a problem with casting the content(int in most cases) to a bufor - some bytes still were missing (e.g 2008 was send instead of 2020). I think there is some problem with conversion, but I used sprintf and wchar_t and it is still not working.
I've got a function:
void send_www(char *buff, int cd){
if(send (cd, buff, strlen(buff), 0) < 0) {
perror ("send()");
exit (1);
which I use here:
// while (fread(znak, sizeof(char), i, handler) != 0) {
for (j = 0; j < i; j++) {
a = fgetc(handler);
sprintf(znak, "%ls", a);
send_www(znak, cd);
}
where i is the length of the image file, znak is the char* (in this version wchar_t*). You can also see my earlier try of using fread.
It's hard to say without more details - can you post some code?
One thing is to make sure you open the image file with the binary option, e.g. fopen(filename, "rb");
If you're just reading a binary file and sending it to a socket where the other end is expecting binary you should not need any casting or sprintf.
You seem to be confusing char type with strings. A C string is a sequence of characters that is zero terminated. Your image file is a binary file containing a sequence of characters but it is not a string. The send() function takes a pointer to a sequence of bytes, not strings. To illustrate this look at this sequence of chars (or bytes):
255, 255, 255, 0, 0, 0, 255, 255, 255
In some image file formats this can be three RGB pixels, so white, black white. 9 bytes. Can be held in a char buffer[9] . If you call strlen() on this you will get the result 3. strlen() counts until it sees a zero character. If you read these bytes from a file without the binary flag it may get transformed and you may get less or more bytes than are really in the file (depending on the contents, the OS etc.).
Rough explanatory code follows:
char buffer[1024];
FILE *infile = fopen("test.gif", "rb"); // open a file (check for failure in real code)
int nread = fread(buffer, 1, 1024, infile);
// assume socket is connected (check for number of bytes sent or error in real code)
send(socket, buffer, nread, 0);
fclose(infile); // close the file
To read from a binary file and send the data out to a socket you need to do something like the snippet above. You would probably keep reading until you reach the end of file, the snippet only reads once. Also in real code you should check to see how many bytes were actually sent (in the return value from send) and keep calling send until you've sent all the data or an error has occured.
You are using strlen(). strlen() stops and returns the size after it reaches a \0 byte. Images and binary data are allowed to have a byte valued zero anywhere, so strlen() is useless in those cases.
You need to modify your function to:
send_www(unsigned char *buff, size_t buf_len int cd);
And pass the image size to it, so you can safely send() it with the appropriate size.
In your case, it seems you are sure it is a wchar_t string, use the appropriate function, wcslen(), not strlen() :)
I'd guess that the problem is that your image data contain characters (\0), so they aren't being sent because you're using strlen() to figure out how much data to send.

Reading a binary file 1 byte at a time

I am trying to read a binary file in C 1 byte at a time and after searching the internet for hours I still can not get it to retrieve anything but garbage and/or a seg fault. Basically the binary file is in the format of a list that is 256 items long and each item is 1 byte (an unsigned int between 0 and 255). I am trying to use fseek and fread to jump to the "index" within the binary file and retrieve that value. The code that I have currently:
unsigned int buffer;
int index = 3; // any index value
size_t indexOffset = 256 * index;
fseek(file, indexOffset, SEEK_SET);
fread(&buffer, 256, 1, file);
printf("%d\n", buffer);
Right now this code is giving me random garbage numbers and seg faulting. Any tips as to how I can get this to work right?
Your confusing bytes with int. The common term for a byte is an unsigned char. Most bytes are 8-bits wide. If the data you are reading is 8 bits, you will need to read in 8 bits:
#define BUFFER_SIZE 256
unsigned char buffer[BUFFER_SIZE];
/* Read in 256 8-bit numbers into the buffer */
size_t bytes_read = 0;
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr);
// Note: sizeof(unsigned char) is for emphasis
The reason for reading all the data into memory is to keep the I/O flowing. There is an overhead associated with each input request, regardless of the quantity requested. Reading one byte at a time, or seeking to one position at a time is the worst case.
Here is an example of the overhead required for reading 1 byte:
Tell OS to read from the file.
OS searches to find the file location.
OS tells disk drive to power up.
OS waits for disk drive to get up to speed.
OS tells disk drive to position to the correct track and sector.
-->OS tells disk to read one byte and put into drive buffer.
OS fetches data from drive buffer.
Disk spins down to a stop.
OS returns 1 byte to your program.
In your program design, the above steps will be repeated 256 times. With everybody's suggestion, the line marked with "-->" will read 256 bytes. Thus the overhead is executed only once instead of 256 times to get the same quantity of data.
In your code you are trying to read 256 bytes to the address of one int. If you want to read one byte at a time, call fread(&buffer, 1, 1, file); (See fread).
But a simpler solution will be to declare an array of bytes, read it all together and process it after that.
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);
It is time to read mans I believe.
Couple of problems with the code as it stands.
The prototype for fread is:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
You've set the size to 256 (bytes) and the count to 1. That's fine, that means "read one lump of 256 bytes, shove it into the buffer".
However, your buffer is on the order of 2-8 bytes long (or, at least, vastly smaller than 256 bytes), so you have a buffer overrun. You probably want to use fred(&buffer, 1, 1, file).
Furthermore, you're writing byte data to an int pointer. This will work on one endian-ness (small-endian, in fact), so you'll be fine on Intel architecture and from that learn bad habits tha WILL come back and bite you, one of these days.
Try real hard to only write byte data into byte-organised storage, rather than into ints or floats.
You are trying to read 256 bytes into a 4-byte integer variable called "buffer". You are overwriting the next 252 bytes of other data.
It seems like buffer should either be unsigned char buffer[256]; or you should be doing fread(&buffer, 1, 1, f) and in that case buffer should be unsigned char buffer;.
Alternatively, if you just want a single character, you could just leave buffer as int (unsigned is not needed because C99 guarantees a reasonable minimum range for plain int) and simply say:
buffer = fgetc(f);

Resources