Can't read file in linux [duplicate] - c

This question already has an answer here:
/proc/[pid]/cmdline file size
(1 answer)
Closed 10 years ago.
I was trying to read the proc/stat file but I couldn't though I am sure that my code is working because I tried reading another files and it worked perfectly ..
here is the code:
#include <stdio.h>
#include <stdlib.h> // for the malloc
int main (int argc,char *argv[])
{
char *file_name = "/proc/stat";
char *contents;
FILE *file;
int filesize = 0;
file = fopen(file_name, "r");
if(file != NULL)
{
//get the file size
fseek(file, 0, SEEK_END);
filesize = ftell(file);
fseek(file, 0, SEEK_SET);
printf("the file size is: %d\n", filesize);
contents = (char *)malloc(filesize+1); // allocate memory
fread(contents, filesize,1,file);
contents[filesize]=0;
fclose(file);
printf("File has been read: %s \n", contents);
}
else
{
printf("the file name %s doesn't exits", file_name);
}
return 0;
}

You cannot determine the size of special files in /proc and you can't seek to the end in them. Their contents are generated on-the-fly. With these files, you have to keep reading until you encounter an EOF. You cannot know how much data you're going to get beforehand.
So keep reading data in, say, 512 byte blocks, until you get a short read. Then you'll know that you can't read any more data.
Edit:
It just occurred to me that I answered this in a past question already: /proc/[pid]/cmdline file size

Related

Copying all file contents into a char array with fread

I'm trying to copy the contents of a file, specifically a PDF file into a character array so that I can send it over the network.
I'm using the fopen with fread for this.
//Get the file path
getFilePath();
//Open the file
fopen_s(&fp, filePath, "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
//allocate memory
buffer = (char*)malloc(sizeof(char)*size);
int charsTransferred = fread(buffer, 1, size, fp);
fclose(fp);
free(buffer);
I have charsTransferred to see how many characters were transferred over by fread. Using size I can tell how many characters should have been moved over, but obviously I'm not getting that many back. Does anyone know what the issue here could be?
There may be a problem in the part of your code you didn't show.
This works:
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
if (fopen_s(&fp, "somepdfile.pdf", "rb"))
{
printf("Failed to open file\n");
exit(1);
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
rewind(fp);
char *buffer = (char*)malloc(sizeof(char)*size);
if (!buffer)
{
printf("Failed to malloc\n");
exit(1);
}
int charsTransferred = fread(buffer, 1, size, fp);
printf("charsTransferred = %d, size = %d\n", charsTransferred, size);
fclose(fp);
free(buffer);
}
Firstly you need to open in binary mode if a PDF, which I believe is a binary format. Then the seek end / ftell method tends to fail for very large files, as well as for text files (which have suppressed characters physically on the disk). There isn't a pure ANSI C way of statting a file, but the function stat() is widely avialable, and gives you file size.

How to write strings in different places of a file in C

in the code below:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
FILE *fp ;
fp = fopen("out.txt", "r+");
int count = 1;
char ch ;
char userInput[5] ;
int lineNumber = 0;
while (lineNumber!= -1){
fgets(userInput, sizeof(userInput), stdin);
lineNumber = atoi(userInput);
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n') //counts number of lines
count++;
if(count == lineNumber)
{
fprintf(fp, "writed %d\n", count);
fseek(fp, 0, SEEK_SET);
}
}
}
return 0;
}
I want to write a string in the line which the user gives me,i store the user answer in userInputand then convert it to the int and store it in lineNumber.
when i try to write fore example in line 90 (my file has 100 lines) two error i get:
1.the file reduce to a 91-line file (instate of remain 100 lines)
2.although i seek to first of file,no more lines written in the next loops and user inputs.
Reading a file (to count its lines) and then turning around and writing to it is tricky. Among other things, you have to do something like an fseek between the reading and the writing. So try interchanging the order of the fseek and fprintf calls:
fseek(fp, 0, SEEK_SET);
fprintf(fp, "writed %d\n", count);
Also, be aware that unless the new text you're writing ("writed ###") is exactly the same length as whatever line used to be there, the line structure of the remainder of the file is likely to get garbled.
See also this question in the C FAQ list.

to read and write contents to a tar.gz file in linux

I am trying to open a tar.gz file and read the contents of that file into a buffer. I want to create another tar.gz file and write the buffer to the newly created tar.gz file. Would the new file be same as the previous one? The code is as follows:
int main()
{
FILE *fp,*fp1;
int len,len1;
int length=0;
char *buf=malloc(1024);
char *buf1=malloc(1024);
fp=fopen("/home/sharwari/Downloads/criu-1.4/3049.tar.gz","rb");
while((len=fread(buf,1024,1,fp))>0)
{
printf("%s",buf);
}
fclose(fp);
fp1=fopen("/home/sharwari/imp5.tgz","wb");
if(fp1==NULL)
printf("\n\terror in creating file...");
len1=fwrite(buf,1,strlen(buf),fp1);
printf("\n\t No. of bytes written: %d",len1);
fclose(fp1);
}
You have the right idea but there are a number of issues with your code. Including at least:
The while loop will result in discarding all except the last 1024 bytes. Because you keep reading 1024 bytes and overwriting the contents of buf.
You cannot use strlen on binary data.
You need more error checking on fread to determine whether you successfully read all the way to the end of the file or whether an error occured. Read the fread man page (it will point you to feof and ferror).
It's good practice to free any malloced memory.
You are calling fwrite(buf,1,strlen(buf),fp1); with wrong arguments.
It should have been
fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
You are trying to read in a block of 1024bytes which will fail if the file size is less than 1024 bytes
With the below code, you are trying to copy byte by byte from source file to
the destination file.
You can refer the below code.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp,*fp1;
int len,len1 = 0;
char buf[1];
fp = fopen("/home/sharwari/Downloads/criu-1.4/3049.tar.gz","rb");
fp1 = fopen("/home/sharwari/imp5.tgz","wb");
if (fp == NULL || fp1 == NULL) {
printf("\n\terror in creating file...");
return -1;
}
while ((len = fread(&buf, 1, 1, fp)) > 0) {
len1 += fwrite(&buf, 1, 1, fp1);
}
printf("\n\t No. of bytes written: %d",len1);
fclose(fp1);
fclose(fp);
return 0;
}
Is it not a bit of overkill fread-ing into a buffer. By definition fopen, fread etc are already buffered and deal with actual io in an optimal manner. The code should be more like
while(1) {
if(i=fgetc(in)==EOF) break;
else fputc(i,out);
}

create fixed length text file in C?

What is the best way to create a empty text file of given length in C? Writing space or any special char is not an option. I mean it should directly create the file without any iteration up to file length or something.
It's pretty trivial to do. All you have to do is to seek the intended position and then write something:
#include <stdio.h>
const unsigned int wanted_size = 1048576;
int main(int argc, char **argv) {
FILE *fp = fopen("test.dat", "w+");
if (fp) {
// Now go to the intended end of the file
// (subtract 1 since we're writing a single character).
fseek(fp, wanted_size - 1, SEEK_SET);
// Write at least one byte to extend the file (if necessary).
fwrite("", 1, sizeof(char), fp);
fclose(fp);
}
return 0;
}
The example above will create a file that is 1 MB in length. Just keep in mind that the actual space will be allocated immediately, not just reserved.
This will also allow you to allocate files larger than your system memory. With the code above I'm able to instantly (< 1 ms) reserve a 1 GB large file on a Raspberry Pi (which only has 512 MB RAM) without having to use any kind of iteration.
You're also able to use any other way to write data to the position (like fputs()), it's just important that you actually write something. Calling fputs("", fp); won't necessarily extend the file as intended.
On Windows use SetFilePointer and SetEndOfFile, on Linux use truncate (which also increases).
This is what I came up with.
// hello.c
#include <stdio.h>
int CreateFileSetSize(const char *file, int size)
{
FILE *pFile;
pFile = fopen(file, "w");
if (NULL == pFile)
{
return 1;
}
fseek(pFile, size, SEEK_SET);
fputc('\n', pFile);
fclose(pFile);
return 0;
}
int main(int argc, const char *argv[])
{
const char *fileName = "MyFile.txt";
int size = 1024;
int ret = 0;
if (3 == argc)
{
fileName = argv[1];
size = atoi(argv[2]);
}
ret = CreateFileSetSize(fileName, size);
return ret;
}
I apparently am not the only one to come up with this solution. I happened to find the following question right here on Stack Overflow.
How to create file of “x” size?
How to create file of "x" size?

How to create an exact copy of file in c

I want to create an exact copy of a file(.bmp) in c
#include<stdio.h>
int main()
{
FILE *str,*cptr;
if((str=fopen("org.bmp","rb"))==NULL)
{
fprintf(stderr,"Cannot read file\n");
//return 1;
}
if((cptr=fopen("copy.bmp","wb"))==NULL)
{
fprintf(stderr,"Cannot open output file\n");
//return 1;
}
fseek(str, 0, SEEK_END);
long size=ftell(str);
printf("Size of FILE : %.2f MB \n",(float)size/1024/1024);
char b[2];
for(int i=0;i<size;i++)
{
fread(b,1,1,str);
fwrite(b,1,1,cptr);
}
fseek(cptr, 0, SEEK_END);
long csize=ftell(str);
printf("Size of created FILE : %.2f MB \n",(float)csize/1024/1024);
fclose(str);
fclose(cptr);
return 0;
}
Although it creates a file of the same size but windows throws an error while trying to view the newly created copy of bitmap.
Why is this happening?
You have moved the file pointer for the input file to the end of the file before you start reading it. You need to restore it to the beginning.
Change:
fseek(str, 0, SEEK_END);
long size=ftell(str);
to:
fseek(str, 0, SEEK_BEGIN);
long size=ftell(str);
fseek(str, 0, SEEK_SET);
Note that your code is devoid of error checking - if you had at least checked the result of fread then your mistake would have been immediately apparent. Take-home message: don't cut corners when it comes to error-checking - it will pay dividends later.
You need to seek back to the start of the original file because you are continually reading at the EOF and therefore not making a copy of the file contents, just whatever happens to be in your b[] array.
You are not checking the return codes of fread() and fwrite(). If you had been doing that you might have solved this problem from the return codes.
If you check the size of the original file and the copy in bytes, it should tell you the issue.
This code reads a byte and writes a byte.
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define KB 1024
int main()
{
unsigned int ifd,ofd,rcnt;
char buf[KB];
ifd=open("orig.jpg",O_RDONLY);
if(ifd==0)
{
fprintf(stderr,"Cannot read file\n");
//return 1;
}
ofd=open("copy.jpg",O_WRONLY|O_CREAT);
if(ofd==0)
{
fprintf(stderr,"Cannot open output file\n");
//return 1;
}
while(rcnt=read(ifd,buf,KB))
write(ofd,buf,rcnt);
}
~
This is a nice function to copy files! Copy char by char is better than read the whole file because that result (if the file is to long) is a bufferoverflow!
double copy(char *input, char *output) {
FILE *f_in = fopen(input, "r");
FILE *f_out = fopen(output, "a");
if (!f_in || !f_out) {
fclose(f_in);
fclose(f_out);
return -1;
}
int c;
while ((c = fgetc(f_in)) != EOF)
fputc(c, f_out);
fclose(f_in);
fseek(f_out, 0, SEEK_END);
long size = ftell(f_out);
fclose(f_out);
return (double)(size / 1024 / 1024); // MB
}
This function returns the MB of the output file. If it wasn't successfully it return 0.
Use this function like this:
double output;
if ((output = copy("What ever you want to copy", "Where ever it should be printed")) != -1)
printf("Size of file: %lf MB.\n", output);
Hope this will help :)
I copped your first code and also used first solution just you need to add this code to your program :fseek(str, 0, SEEK_SET);and done your copy bitmap will be produce.

Resources