File I/O management in C - c

My first post :), am starting out with C language as basic learning step into programming arena. I am using following code which reads string from text file, makes directory with that string name and opens a file for writing in that created directory. But am not able to create a file inside directory made, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <string.h>
int main()
{
char file_name[25], cwd[100];
FILE *fp, *op;
fp = fopen("myfile.txt", "r");
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
fgets(file_name, 25, fp);
_mkdir(file_name);
if (_getcwd(cwd,sizeof(cwd)) != 0)
{
fprintf(stdout, "Your dir name: %s\\%s\n", cwd,file_name);
op = fopen("cwd\\file_name\\mynewfile.txt","w");
fclose(op);
}
fclose(fp);
return 0;
}

What you need is to store the file name (with the path) in a c-string before opening. What you are opening is cwd\file_name\mynewfile.txt. I doubt that your directory is named cwd.
A sample could could be:
char file_path[150];
sprintf(file_path, "%s\\%s\\mynewfile.txt", cwd, file_name);
op = fopen(file_path,"w");

use
#include <sys/stat.h>
#include <sys/types.h>
instead of
#include <direct.h>
and modify
op = fopen("cwd\\file_name\\mynewfile.txt","w”);

I see you are using the return values. That is a good start for a beginner. You can refine your error messages by including "errno.h". Instead of printing your own error messages call
printf("%s", strerror(errno));
You get more precise error messages that way.

op = fopen("cwd\\file_name\\mynewfile.txt","w”);
You’re actually passing the string literals “cwd” and “file_name” as part of the path of the file, when I think you actually mean to put the contents of the variables with those names in there. You will probably have to piece together a string for the path. Try looking into strcat()
http://www.cplusplus.com/reference/cstring/strcat/

Related

How to read a configuration file, or create one if it's missing

How do you make a file, but only if it doesn't already exist? Like.. I want to read a text file, but if it doesn't exist, I want to create one with some default text.
I can create the file with the default text easy enough. And I can append or overwrite it if it already exists.
But if it already contains some text, I want to READ FROM it. Not WRITE TO it. Like you might do with a dot file or configuration file, to set a default configuration in the event the file is missing.
This is quite simple with Python, but I'm trying to make the transition to C, and It's more challenging than I'd anticipated.
So my function basically looks something like this so far. The text is just a placeholder for whatever the real text might be.
main() {
FILE *fp;
fp = fopen("./filename.txt", "w");
fprintf(fp, "some default text\n");
fclose(fp);
}
So just to clarify: If ./file.txt already exists, it shouldn't be written to. It should be read from.
When I say "read from", it could be printed to stdout, or stored in an array for instance, but that's probably beyond the scope of the question.
Considering your example there are two main mistakes:
You don't check the result of fopen thus you don't know whether your file has been successfully opened (here is the key to the answer).
printf function prints directrly to stdout and you have to use fprintf one for printing to your configuration file.
I propose the following: try to fopen your configuration file (e.g. ./filename.txt) for r and check the result of this call. Upon successful completion fopen return a FILE pointer to your existing configuration file. If the file doesn't exist fopen returns NULL and errno is set to ENOENT. In this case you can create a new configuration file and write a default config into it.
Please see man 3 section for the corresponding docs.
UPD:
Here is PoC for the proposal
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
FILE *fp = fopen(".rc", "r");
if (!fp)
switch (errno) {
case ENOENT:
fprintf(stderr, "No config found, creating the default one\n");
fp = fopen(".rc", "w");
if (!fp) {
perror("Failed to create default config: ");
return EXIT_FAILURE;
}
/* write default config here */
break;
default:
perror("Failed to open existing config: ");
return EXIT_FAILURE;
}
/* read existing config here */
return EXIT_SUCCESS;
}
Use stat before opening your file. If the stat is successful then the file exists, if it is not, check for ENOENT in errno.
Example
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
struct stat file_infos;
char file_path[] = "/whatever"
if (stat(file_path, &file_infos) != 0)
{
if (errno == ENOENT)
{
// Do whatever when the file wasn't found
}
else
{
// Error accessing the file, check the errno for more infos
}
}
else
{
// File exists, do whatever you like with it.
}
}
Enjoy :)

How to read data from all files in a directory using C Language?

I am trying to 1) Find all files in a directory and display them, 2) Open all found files and read data from them (characters) 3) Output the read data to the screen or a new file.
This is done in C Language and you will see below my current code. The problem that I am running into is that: I can find all the files in my directory and print them to the screen just fine (point 1 above), but when I try to open the found files and read data (characters) from them (point 2 above), I get a segmentation fault.
If I comment out the fscanf(entry_file, "%s", files); line below, but leave the entry_file = fopen(in_file->d_name, "r"); line, it compiles okay and writes the files to the screen. I also tried indexing the fscanf line with the int i (not shown below) and produced the same segmentation fault.
So, how can I read data from these found files? Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
int main()
{
DIR* dir;
FILE *entry_file;
struct dirent *in_file;
char files[1000];
int i;
dir = opendir("/Users/tcn/data");
if(dir==NULL){
printf("Error! Unable to read directory");
exit(1);
}
while( (in_file=readdir(dir)) != NULL) {
if (!strcmp (in_file->d_name, "."))
continue;
if (!strcmp (in_file->d_name, ".."))
continue;
printf("%s\n", in_file->d_name);
entry_file = fopen(in_file->d_name, "r");
fscanf(entry_file, "%s", files);
}
closedir(dir);
fclose(entry_file);
return 0;
}
Seeing as you are correctly checking for NULL against dir and in_file before using them, the only other thing that could possibly be causing this is entry_file being null. Check it before using it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
int main()
{
DIR* dir;
FILE *entry_file;
struct dirent *in_file;
char files[1000];
int i;
dir = opendir("/Users/tcn/data");
if(dir==NULL) {
printf("Error! Unable to read directory");
exit(1);
}
while((in_file=readdir(dir)) != NULL) {
if (!strcmp (in_file->d_name, "."))
continue;
if (!strcmp (in_file->d_name, ".."))
continue;
printf("%s\n", in_file->d_name);
entry_file = fopen(in_file->d_name, "r");
if (entry_file != NULL) {
fscanf(entry_file, "%s", files);
/* whatever you want to do with files */
fclose(entry_file);
}
}
closedir(dir);
return 0;
}
Note also that, as multiple other users have commented, you should close entry_file within the loop.
The two most likely causes of the crash are not checking the return value of fopen – then either the fscanf or the fclose may crash when attempting to use entry_file when it's NULL – and the potential overflow of files.
Another problem which does not cause a crash is that the in_file->d_name does not contain the full path, but only the name of the file. So if you are testing the code inside /Users/tcn/data then it will appear to work, but it will fail elsewhere. Either prefix the filename with /Users/tcn/data/ or operate only on the current directory (.).
Fixes:
if ((entry_file = fopen(in_file->d_name, "r"))) {
(void) printf("%s\n", in_file->d_name);
if (fgets(files, sizeof files, entry_file)) { // or `while`?
// do something with `files`, it will be overwritten for next file
}
(void) fclose(entry_file);
}
And remove the other fclose(entry_file) from the end of the code.
Also note that if you use this code with an arbitrary directory, it might contain pipes and/or device nodes that will hang forever when you attempt to read them.
You will need a function with a loop using fread() to replace the fscanf line, and do a hex dump. For one thing, you don't know if the files are text files or binary files. For another, the segfault could be coming from reading a binary file that contains no newline into char files[1000]; And even if the files are all text files, you cannot predict that your "generous" 1000 length is enough to hold the first line of text.

Without using remove() function How to delete a file in C program

I am trying to delete a file in c program. Assume that the file is located in current directory of source file. I have searched a lot but didn't get any solution. Everyone is suggesting to use remove() function.
Here is my source code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
int delete_status;
char del[50];
printf("Enter a file name to delete it: ");
gets(del);
delete_status = remove(del);
if(delete_status!=0) {
printf("File can not be deleted!\nFile does not exist in current directory\n");
}
else printf("File %s has been deleted successfully!\n", del);
return 0;
}
Is there any way to remove file without using remove() function. I want to code manually without using any other stl built in function.
You can replace remove() with unlink() (for files) and rmdir() (for directories).
You can check this answer. You should try to read a system programming book where you can learn about uses like INTERNAL_SYSCALL.
You can skim through the functions referred in the posts like unlink() etc.
EDIT: actually somehow you will end up using a system-call at some level. You probably trying to achieve the operation of deleting a file from different abstraction level.(remove() system call will also use INTERNAL_SYSCALL which nothing but a system call).
Now from low level deleting a file doesn't mean we are erasing something. We are just considering the space as free space(free pool of memory) and then any metadata related to that file is also freed. To achieve that you need to implement a filesystem that allocates memory,deletes it..using device level instructions.
Call unlink for files, rmdir for directories. You could easily check which a file is using stat and then call the correct function.
struct stat sb;
if (!stat(filename, &sb))
{
if (S_ISDIR(sb.st_mode))
rmdir(filename);
else
unlink(filename);
}
Include <sys/stat.h> for stat and S_ISDIR, <unistd.h> for rmdir and unlink.
Oh, and per your comment:
All of you didn't understand my needs and requirement. I know that it is posible to delete a file using standard library function like remove(), unlink(), rm() etc. But I want to code manually without using any built in function.
Have fun reproducing unlink's source code.
I think what you need to know is unlink() function. For deleting files, remove() internally calls unlink() itself. Check the man page for details.
However, first I suggest you to change the gets() with fgets(). Also, int main() should be int main(void).
One can use fork and exec to run the rm command over shell.
sample code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int status;
pid_t pid = fork();
if(-1 == pid){
printf("fork() failed");
exit(EXIT_FAILURE);
}else if(pid == 0){
execl("/bin/sh", "sh", "-c", "rm /tmp/sandeep_reve.txt", (char *) NULL);
}else{
printf("Fork with id %ld\n",(long)pid);
waitpid(pid,&status,0);
}
return 0;
}
Use system():
PART I:(Delete file)
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int delete_status;
char path[100],order[]="del ";//del for delete file, if change del to rd is delete folder(**Code at part 2)
printf("Enter a path of file to delete it: ");
gets(path);
strcat(order,path);//Order
fp = fopen(path,"r");
if(fp != NULL){//Check file whether or not exist
fclose(fp);
system(order);//Del file
printf("Delete successfully");
}else{
perror("ERROR");
fclose(fp);
}
return 0;
}
For example, you want to delete 1.txt.Then, you may put the c program in the same file and then intput 1.txt or enter whole path of the file.(e.g C:\User\desktop\1.txt)
PART II :(Delete folder)
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int delete_status,i = 1;
char path[100],order[] = "rd ";//del -> rd
printf("Enter a path of file to delete it: ");
gets(path);
strcat(order,path);
system(order);
return 0;
}

C program fopen() does not open a file

I understand, there are thousands of problems like this, but I haven't managed to find the solution to my issue. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
FILE *inputFile=fopen("I:\\Test\main.cpp","R");
FILE *outFile=fopen("I:\\Test\main2.cpp", "W");
if (inputFile==NULL) {
printf("Unable to locate source file");
_getch();
return 1;
}
int c;
int inSingleLine=0;
int inMultiLine=0;
int d=fgetc(inputFile);
while(c=fgetc(inputFile)!=EOF){
if (d==EOF) break;
if((c=='/') && (d=='*')) inMultiLine=1;
if ((c='*') && (d=='/')) inMultiLine=0;
if((c=='/')&& (d=='/')) inSingleLine=1;
if (c='\n') inSingleLine=0;
if (!inSingleLine && !inMultiLine) {
putc(c,outFile);
}
d=getc(inputFile);
}
// This is a test string
fclose(inputFile);
fclose(outFile);
/* And this is not a test
Actually not
*/
return 0;
}
No matter what I do, whether I put main.cpp to the same folder with the exe file and make it FILE *inputFile=fopen("main.cpp","R"); or specify an absolute path, I get "Unable to locate source file" all the time.
Please help!
The mode strings for read and write mode are "r" and "w", not "R" and "W". Using an invalid mode is probably what's causing fopen to fail.
int main()
{
FILE *inputFile=fopen("I:\\Test\main.cpp","R"); <-- This results in the string "I:\Testain.cpp"
...
Make sure you use two "\" symbols (escape both back-slashes), and use lower-case "w" and "r":
FILE *inputFile=fopen("I:\\Test\\main.cpp","r");
As above, you must "escape" a backslash with a double one. You should always check the return value from fopen() and then you can obtain a message based on errno. When I tried the following with a lower-case "r" I got a compiler warning about the invalid escape sequence \m but the program was well behaved.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *inputFile=fopen("I:\\Test\main.cpp","r");
printf("After trying to open\n");
if (inputFile == NULL)
printf ("%s\n", strerror(errno));
else
fclose(inputFile);
return 0;
}
I got:
After trying to open
No such file or directory
But when I tried it with an upper-case "R" the program hung (MSVC), I don't know why.

Read text into C. Get a bad exec error

Trying to learn C. Want to read the first line of a text file, my code is:
#include <stdio.h>
int main()
{
FILE *in = fopen("test.txt", "rt");
// read the first line from the file
char buffer[100];
fgets(buffer, 20, in);
printf("first line of \"test.txt\": %s\n", buffer);
fclose(in);
return 0;
}
I'm doing this in xCode. I get a exc bad access error.
test.txt definitely exists. It has one line that says "this is a text file"
try this after fopen() call:
if(in == NULL){
printf("Can't read teste.txt because: %s.\n", strerror(errno));
return 1;
}
and add the headers:
#include <errno.h>
#include <string.h>
The code looks fine, so my guess is that the program is not run in the same working directory as the file. Try placing the file in, say, /tmp/test.txt and use absolute path in fopen.
You don't check if the FILE is NULL. It may not be opened for a several reasons.

Resources