fread only reading 64 bytes? - c

As the title says, freads appears to only be reading the first 64 characters. Relevant code:
FILE* sigD = fopen("signature", "r");
char *sig[255];
fread(sig, 255, 255, sigD);
close(sigD);
fputs(sig, stdout);
Console output:
user#PC:~$ ./a.out --has-sig
;2F*S|tr;;E9;Yb=R6)!fcXhoX#RC`#NzLy<}w#T+uvH${3Et&9K&-0~%D{1
user#PC:~$
user#PC:~$ cat signature
;2F*S|tr;;E9;Yb=R6)!fcXhoX#RC`#NzLy<}w#T+uvH${3Et&9K&-0~%D{1N{7ry:-B9b:kGB=Gkk9V+Cc$8a&35W{15Q~#-+PMeqa;#cKA7Ew3G6P4smDdJWV2#>R!V#ki#(Xj<a,^B)qJ5D&bON//?%/!G)XA&m|8:1mVHmx{7nQoRJ%v{(K:;JtX2hOm/dhVm9mnuDMSbQX55ouVnmECbA`/`!?=Mh0Ab^#vk*K*HG5$omu6716/Loh1Ht
h
As that log shows, there is 254 characters in the file, but only 64 are getting read.
EDIT: problem wasn't with fread, I had accidentally written in zero-terminators into the file.

It is not clear if this is related, but there seems to be a couple problems:
char *sig[255];
fread(sig, 255, 255, sigD);
The call to fread is not consistent with the declaration. It should maybe be the following (you probably want an array of char rather than an array of pointers to char). And the size/nitems info passed to fread was not correct:
char sig[255];
// initially I had this as 'sizeof(), 1' but I think for this file it would make
// more sense as the following (nitems=255):
fread(sig, 1, sizeof(sig), sigD);
And while it should not matter, you might try opening it with a mode of "rb" to force a binary open (the b for binary is supposed to be ignored on POSIX conforming systems).

Your definition of sig is incorrect. If you want an array of characters you must remove the asterisk. You have defined an array of character pointers. It should look like:
char sig[255];

Related

puts and printf do not give out full text (text containing CJK characters), when the text is read from a local file, on Windows, MSVC

The text contains:
..... (some characters can't be posted on SO)
xxxxxxxx=xxx xxxxxxx=xxxxx://xxx..xxx/xxxxx/xx9528994
(for full text & data please see https://github.com/ggaarder/snippets/raw/master/x.txt)
which is ended in xxxxx://xxx..xxx/xxxxx/xx9528994, however, when reading it then puts, it only gives out
..... (some characters can't be posted on SO)
xxxxxxxx=xxx xxxxxxx=xxxxx:/
which only prints to xxxxx:/, and /xxx..xxx/xxxxx/xx9528994 is missed.
Code to test:
#include <stdio.h>
int main(void)
{
char s[30000];
FILE *f = fopen("x.txt", "r");
fread(s, sizeof(s), 1, f);
puts(s);
return 0;
}
The buffer size 30000 is adequate. x.txt is 1049 bytes.
You can download x.txt at https://github.com/ggaarder/snippets/raw/master/x.txt, for convenience I have packed everything to https://github.com/ggaarder/snippets/raw/master/foo.zip.
It will be very kind of you to download and take a look of x.txt, since most part of it can't be posted on SO because of the special characters, including some CJK.
Attempts:
The whole file is read properly. #pmg notices that fread returns zero, while #Someprogrammerdude points out that if fread's size and count arguments are swapped fread returns 1049, and this supports the guess.
If the CJK letters are removed, the output will be totally OK. So I think there is no '\0' in the middle.
By adding
ret = puts(s);
printf("\nret: %d, %s", ret, strerror(errno));
We will get ret: 0, No error. puts return zero and there's nothing in errno.
You may notice that there's a heading \n in 3.. Yes, puts doesn't gives out the newline as usual - does this suggest that puts failed?
But why does it returns zero and there's nothing in errno?
May it be related to Windows NT cmd? Maybe some special terminal control letters are unintentionally out.
Reading by rb is the same. x.txt is an XML text, just for convenience I removed part of it that are the irrelevant, so it looks like spam.
I guess this is just yet another encoding issue, plus some magical secret Windows commandline control sequence .... I'm not taking it. I will just erase all non-ASCII characters.
The order of the "size" and "count" arguments to fread is crucial.
The first argument is the "element" size, and the second argument is the number of elements to attempt to read.
In the case of a text file, the element size is a single character, usually a single byte. The number of elements to attempt to read is the size of the destination array.
So your call should be
fread(s, 1, sizeof s, f);
instead.
What happens now when you have the opposite is that you say that the "element" size is 30000 bytes, and that fread should read one such element. Since the size of the file is less than 30000 bytes, it just can't read even a single element, and returns 0 to indicate it.
open the file in binary mode
switch arguments and check the return value of fread().
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char s[30000];
FILE *f = fopen("x.txt", "rb"); // binary mode
unsigned long len = fread(s, 1, sizeof(s), f); // switch args, check value
if (len < 1) {
perror("bad fread");
exit(EXIT_FAILURE);
}
s[len] = 0; // properly terminate s
puts(s);
return 0;
}
It's just yet another encoding issue happening everyday. Just SetConsoleOutputCP(65001) or /utf-8 or set execution code page in #pragma and everything will be fine.

Printing file content, help for understanding different outputs [duplicate]

I would like to copy binary file source to file target. Nothing more! The code is inspired from many examples found on the Internet.
#include <stdio.h>
int main(int argc, char **argv) {
FILE *fp1, *fp2;
char ch;
fp1 = fopen("source.pdf", "r");
fp2 = fopen("target.pdf", "w");
while((ch = fgetc(fp1)) != EOF)
fputc(ch, fp2);
fclose(fp1);
fclose(fp2);
return 0;
}
The result differs in file size.
root#vm:/home/coder/test# ls -l
-rwxr-x--- 1 root root 14593 Feb 28 10:24 source.pdf
-rw-r--r-- 1 root root 159 Mar 1 20:19 target.pdf
Ok, so what's the problem?
I know that char is unsigned and get signed when above 80. See here.
This is confirmed when I use printf("%x\n", ch); which returns approximately 50% of the time something like sometimes FFFFFFE1.
The solution to the my issue would be to use int i.s.o. char.
Examples found with char: example 1, example 2
example 3, example 4, ...
Examples found with int: example a, ...
I don't use fancy compiler options.
Why are virtually all code examples found returning fgetc() to an char i.s.o. an int, which would be more correct?
What am I missing?
ISO C mandates that fgetc() returns an int since it must be able to return every possible character in addition to an end-of-file indicator.
So code that places the return value into a char, and uses it to detect EOF, is generally plain wrong and should not be used.
Having said that, two of the examples you gave don't actually do that.
One of them uses fseek and ftell to get the number of bytes in the file and then uses that to control the read/write loop. That's could be problematic since the file can actually change in size after the size is retrieved but that's a different problem to trying to force an int into a char.
The other uses feof immediately after the character is read to check if the end of file has been reached.
But you're correct in that the easiest way to do it is to simply use the return value correctly, something like:
int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
doSomethingWith(charInt);
Well the thing is most of code you saw then is wrong. There are 3 types of char - signed, unsigned and plain char. Now if plain char is by default signed then a character with decimal value 255 will be considered equal to -1 (EOF). This is not what you want. (Yes decimal value 255 won't be representable in signed char but it's implementation defined behavior and on most ones it will store the bit pattern 0xFF in the char).
Secondly if char is unsigned then it EOF will be considered as 0xFF that is also wrong now and comparison would fail. (Knowing that EOF is -1 it will be converted to CHAR_MAX which is 255 or 0xFF).
That's why int is considered so that it can hold the value of EOF correctly and that is how you should use it.

What is the use of `putw` and `getw` function in c?

I wanna know the use of putw() and getw() function. As I know, these are used to write and read from file as like as putc and getc but these deals with only integers. But when I use these for writing integers, it just write different symbol in file (like if I write 65 to file using putw(). It writes A in the file). Why does it take the ASCII value? I am using codeblocks 13.12. Code:
#include <stdio.h>
int main() {
FILE *fp;
int num;
fp = fopen("file.txt", "w");
printf("Enter any number:\n");
scanf("%d", &num);
putw(num, fp);
fclose(fp);
printf("%d\n", num);
return 0;
}
Let's read the point to point explanation of getw() and putw() functions.
getw() and putw() are related to FILE handling.
putw() is use to write integer data on the file (text file).
getw() is use to read the integer data from the file.
getw() and putw() are similar to getc() and putc(). The only difference is that getw() and putw() are especially meant for reading and writing the integer data.
int putw(integer, FILE*);
Return type of the function is integer.
Having two argument first "integer", telling the integer you want to write on the file and second argument "FILE*" telling the location of the file in which the data would be get written.
Now let's see an example.
int main()
{
FILE *fp;
fp=fopen("file1.txt","w");
putw(65,fp);
fclose(fp);
}
Here putw() takes the integer number as argument (65 in this case) to write it on the file file1.txt, but if we manually open the text file we find 'A' written on the file. It means that putw() actually take integer argument but write it as character on the file.
So, it means that compiler take the argument as the ASCII code of the particular character and write the character on the text file.
int getw(FILE*);
Return type is integer.
Having one argument that is FILE* that is the location of the file from which the integer data to be read.
In this below example we will read the data that we have written on the file named file1.txt in the example above.
int main()
{
FILE *fp;
int ch;
fp=fopen("file1.txt","r");
ch=getw(fp);
printf("%d",ch);
fclose(fp);
}
output
65
Explanation: Here we read the data we wrote to file1.txt in above program and we will get the output as 65.
So, getw() reads the character 'A' that was already written on the file file1.txt and return the ASCII code of the character 'A' that is 65.
We can also write the above program as:
int main()
{
FILE *fp;
fp=fopen("file1.txt","r");
printf("%d",getw(fp));
fclose(fp);
}
output
65
If num is an int, then putw(num, fp) is equivalent to fwrite(&num, sizeof(int), 1, fp), except for having a different return value. It writes an int to the file in binary format. getw is similar but with fread instead. You can see how glibc implements them: putw,getw.
This means that:
They are not appropriate for writing text. If you want to write a number to a file in human-readable decimal or hexadecimal format, use fprintf instead.
They typically read/write more than one byte (one character) to the file. For instance, on a machine with 32-bit ints, they will read/write four bytes. Attempting to do putw('c') will not simply write the single character 'c'.
They should only be used with files opened in binary mode (if that makes a difference on your system).
You should not expect the contents of the file to be human-readable at all. If you attempt to view the file in an editor, you'll see the representation of whatever bytes are in the file, in your current character set (e.g. ASCII).
You should not expect the file to be successfully read back on another computer that uses a different internal representation for int (e.g. different width, different endianness).
On a typical system with 32-bit little-endian int, putw(65, fp) will result in the four bytes 0x41 0x00 0x00 0x00. The 0x41 (decimal 65) is the ASCII code for the character A, so you'll see that if you view it. The 0x00 bytes may or may not be displayed at all, depending on what you are using to view.
These function are not a good idea to use in new code. Even if you do need to store binary data in files, which has various disadvantages as noted and should usually only be done if there is a very good reason for it, you should simply use fwrite and fread. getw/putw are a worse option because:
They will make your code less portable. fwrite/fread are part of the ISO C standard, which is the most widely supported cross-platform modern standard for the C language. getw/putw were present in the Single Unix Specification v2 version 2, which dates to 1997 and is now obsolete. They were not included in the POSIX/SUSv3 specs which superseded SUSv2, and it would be unwise to count on them being available on new systems.
They will make your code less readable. Since fread/fwrite are far more widely used, another programmer reading your code will recognize immediately what they do. Since getw/putw are more obscure, people are likely to have to go and look them up, and the names don't make it easy to remember that they operate specifically on the type int. Readers may also confuse them with the similarly-named ISO-standard functions getwc/putwc. So using getw/putw makes your code less readable.
They may introduce subtle bugs. getw returns EOF on end-of-file or error, but EOF is a valid integer value (often -1). Therefore, if it returns this value, you cannot easily tell whether the file actually contained the integer -1, or whether the read failed. And since this only happens for one particular value, it may be missed in testing. You can check ferror() and feof() to distinguish the two cases, but this is awkward, easy to forget to do, and negates most of the apparent convenience of the "simpler" interface of getw compared to fread.
I speculate that the only reason these functions existed in the first place is that, like putc (respectively getc), putw could be implemented as a macro that directly wrote the buffer of fp and would thus be a little more efficient than calling fwrite. Such an implementation is no longer feasible on modern systems, since it wouldn't be thread-safe, so putw needs a function call anyway. In fact, with glibc in particular, putw just calls fwrite after all, with the overhead of an additional function call, so it's now less efficient. So there is no longer any reason at all to use these functions.
From the man page of putw() and getw()
getw() reads a word (that is, an int) from stream. It's provided for compatibility with SVr4.
putw() writes the word w (that is, an int) to stream. It is provided for compatibility with SVr4.
You can use the fread and fwrite function for better use.
getw() reads the integer from the given FILE stream.
putw() it write the integer given in the first argument into the file pointer.
getw:
It will read the integer from the file. like getchar() doing the work. Consider the file having the content "hello". It will read the h and return ascii value of h.
putw:
It will place the given integer, integer taken as a ascii value. Corresponding value of the ascii value placed in the file. like putchar()

fgets not reading the beginning of a line

I am having trouble reading a few lines of text from a file using fgets. The file is some basic user data that is written to a file within the bundle the first time the plugin is launched. Any subsequent launch of the plugin should result in the user data being read and cross referenced to check the users authenticity.
The data is always 3 lines long and is written with frwite exactly as it should be and is opened with fopen.
My original theory was to just call fgets 3 times reading each line into it's own char array which is part of a data struct. The problem is the first line is read correctly, the second line is read as though the position indicator starts on the next line but offset by the number of characters read from line 1. The third line is then not read at all.
fgets is not returning any errors and is behaving as though it has read the data it should have so i'm obviously missing something.
Anyway here's a portion of my code hopefully someone can some shed some light on my mistakes!
int length;
fgets(var.n, 128, regFile);
length = strlen(var.n);
var.n[length-1] = NULL;
fgets(var.em, 128, regFile);
length = strlen(var.em);
var.em[length-1] = NULL;
fgets(var.k, 128, regFile);
length = strlen(var.k);
var.k[length-1] = NULL;
fclose(regFile);
Setting the last character in each string to NULL is just to remove the /n
This sequence of code outputs the whole of line 1, the second half of line 2 and none of line 3.
Thanks to #alvits for the answer to this one:
fwrite() is not compatible with fgets(). Files created using fwrite() should use fread() to read them ?>back in. Both fwrite() and fread() operates on binary streams unless explicitly converted to and from >strings. fgets() is compatible with fputs(), both operates on strings.
I used fputs() to write my data instead and it read back in perfectly.
In POSIX systems, including Linux, there is no differentiation between binary and text files. When opening a file stream, the b flag is ignored. This is described in fopen().
You might ask "how would you differentiate text from binary files?". The contents differentiate them. How the contents are written makes them a binary or text file.
Look at the signature size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream). You'll notice that it writes the contents of *ptr with size describing the size of each members, nmemb. The written stream is not converted to string. If you were to write 97 it will write the binary 97 which in ascii is A. Binary data does not obey string terminations. Presence of \n and \0 in data is literally written as is.
Now look at the signature int fputs(const char *s, FILE *stream). It writes the string content of *s. If you were to write 97, it will have to be a string "97" which is not A. String termination is obeyed. \n is automatically converted to the O/S supported newline (CRLF or LF).
You can coerce fwrite() to behave like fputs() but not the other way around. For example, if you declare ptr as a pointer to string and calculate the size exactly as the length of the content excluding string terminator, you'll be able to write it out as text instead of binary. You will also need to handle \0 and \n and convert them to O/S supported newline. Writing the entire string buffer will write everything including and past the string terminators.

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.

Resources