I have written a program, where it takes an input file, does some operations on it and gives its corresponding output file. i.e., for inp1.txt output is out1.txt, for inp2.txt output is out2.txt and so on, both in different folders.
Right now I have used a file_count variable and have used switch case method, to open the particular file.
The problem is, if I add one more file to the folder, then I have to re-edit the program with another case statement.
Please suggest me the usage of directory pointer in , I browsed all over the net but didnt get an exact solution.
Thanks a lot in anticipation.
There's no way to read the contents of a directory using only standard C APIs, so you'll have to use platform-specific APIs instead:
On *nix systems, you use opendir(3)/readdir(3)/closedir(3) to read the contents of a directory.
On Windows systems, you use FindFirstFile/FindNextFile/FindClose
If you know the file names in advance ie. they follow a pattern like this: f1.txt f2.txt fn.txt then you can loop over the files:
for (int i = 0 -> num_files)
char * filename;
filename = create_your_filename(i)
open(filename)
dostuff
close(filename)
you can follow the same pattern or even edit the filename for the output files.
Otherwise you can also call the program with all the input files in the command:
your_program *.txt
Then all of the file names will appear in argv[], which you can iterate over.
you have to find the files in input folder in runtime before processing. you can sort the files by extension,file name,created date etc...
Here is a simple function that show you if a file (in parameters) is in the path you put in argument.
Return 0 if file exit, 1 if not.
int is_file_enabled(char *path, char *filename)
{
char exec[255], line[255];
sprintf(exec, "ls %s | grep \"%s\"", path, filename);
FILE* cmd_res = popen(exec, "r");
if (cmd_res != NULL)
while (fgets(line, sizeof(line), cmd_res) != NULL)
if (line != NULL) { pclose(cmd_res); return 0; }
pclose(cmd_res);
return 1;
}
Related
I am trying to rename a bunch of files in a user specified directory, but it only seems to be working when the user specifies the directory that the program is running from. For example, when running from the command line:
./a.out . "NewName.txt" will work, while
./a.out .. "NewName.txt" will not work. Is there a reason for this? It's on Linux, by the way.
int main(int argc, char** argv){
char* dirpath = argv[1];
char* newName = argv[2];
DIR *d;
struct dirent *dir;
d = opendir(dirpath);
if (d){
while ((dir = readdir(d)) != NULL){
char* filename = dir->d_name;
if (rename(filename,newName) == 0){
printf("Renaming %s -> %s\n",filename,newName);
} else {
printf("Could not rename %s\n",filename);
}
}
}
closedir(d);
}
I have also tried (while running the program from outside of Desktop):
if (rename("~/Desktop/test.txt","~/Desktop/test2.txt") == 0){
printf("Renaming %s -> %s\n",filename,newName);
} else {
printf("Could not rename %s\n",filename);
}
and it still fails.
While readdir() is reading file names from the other directory, your program's current directory is still in a different location. Unless you prefix the source file name with the path to the directory (and the destination file name too) you're trying to rename non-existent files in the current directory, in general.
In pseudo-code:
dir = opendir(remote_directory)
foreach name from dir
rename "remote_directory/name" to "remote_directory/othername"
end for
Note that the pseudo-code works if 'remote_directory' happens to be ., the current directory; you don't need to special-case that code.
I believe that your main problem is that the result from readdir is just the filename. It doesn't include the directory. You need to paste the directory name and the filename from dir->d_name together in your program.
From the documentation:
The old argument points to the pathname of the file to be renamed.
The new argument points to the new pathname of the file.
If the new argument does not resolve to an existing directory entry for a
file of type directory and the new argument contains at least one non-<slash>
character and ends with one or more trailing <slash> characters after all symbolic
links have been processed, rename() shall fail
Looks like you're not referring to an existing element when you use any path other than '.', which is likely why it's failing.
Check the specific errno value to see why.
I am using fopen(3) in C to read file and process it. The file is present in current working directory where the binary exists, but I am unable to read the file (Linux environment / Cygwin environment).
Here is the sample code:
C code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
FILE *inFile;
static char fileName[255];
int process_file(FILE *inFile)
{
char ch;
inFile = fopen(fileName,"r");
if (inFile == NULL)
{
perror(fileName);
exit(1);
}
else
{
// Process file
}
fclose(inFile);
return 0;
}
int main(int argc, char *argv[])
{
printf("Enter filename to process \n");
scanf("%s", fileName);
process_file(inFile);
getchar();
return 0;
}
I have file permissions set to 777 in the current directory. The resulting binary as well as my source code reside in this directory where the input file exits. Why is the file not opened?
Update :
This question was written in few years back and this code could be improved a lot.
1. The process file should accept char * or char array instead of file pointer
2. unused variables can be removed
3. unused libraries or include files can be removed
4. Can make use of argv to accept filename with path from cmdline
5. return instead of exit in process_file and also proper return code instead of returning 0 from process_file.
I should have asked this question little more elaborate...
I had three functions to process the same file, like process_fil1e1(), process_file2() and process_file3() even though I called fclose() in all three functions. Somehow the file handle was not closed that properly or the file pointer pointed to EOF or some undefined behavior. It was not working fine.
When I used a single process file and rewind() together, it worked fine...
Be sure to input file name with its extension. This may cause problems with reading the file.
If you know the extension of the file you can input only the name and after that make the program add the extension. After scanf("%s", fileName); add strcat(fileName, ".txt"); if you want to enter only the name without extension and the file you read has extension .txt.
Your inFile and fileName variables are extern so you don't need to have arguments for the function process_file();, any function can access those variables.
You can change function int process_file(); to void process_file(); and delete return 0, you don't need that.
You have declared the inFile and fileName as global. You should change your function prototype from
int process_file(FILE *inFile)
to
int process_file()
This would at least make your program more clear. Now regarding your problem: It would almost certain be that you are doing something wrong in the input file (like not putting in the file extension) in your input. Remember, you need to pass the complete file name (including the extension which on some systems like Windows (by default) would be hidden). Otherwise, the logic looks correct to me, and it should work fine.
I have a text filed called fun on my desktop, but when I pass:
FILE* fp;
if((fp = fopen("/Users/<username>/Desktop/fun", "r")) == NULL)
{
printf("File didn't open\n");
exit(1);
}
fp is null. I have also tried
/home/<username>/Desktop/fun
and many variations, and I still can't seem to get the right file path.I am new to using files and C. Any help would be appreciated.
fopen() can't expand shell keywords.
Change
FILE* fp = fopen("~/Desktop/fun.txt", "r")
to
FILE* fp = fopen("/home/<yourusername>/Desktop/fun.txt", "r")
Characters like '~', '*' are interpreted by the shell and expanded.
You can't use ~ in pathnames to represent the user's home directory. That notation is recognized by shells and some other applications, but it's not part of the Unix filesystem interface. You need to spell out the user's actual home directory.
fopen("/home/username/Desktop/fun.txt", "r")
The ~ in the path is probably the issue. It's your shell that expands that on the command line. fopen doesn't invoke a shell to do substitutions on the path, you'll need to do that yourself.
So pass a complete (relative or absolute) path to fopen, not something that requires shell expansions (~, globbing patterns or shell variables).
You need to expand ~. Use getenv("HOME").
getenv at opengroup even provides some code:
const char *name = "HOME";
char *value;
value = getenv(name);
/*===exphome===([o]i)==================================================
* if SIn is not NULL then
* if SIn starts with '~'
* then expands $HOME, prepends it to the rest of SIn, and
* stores result in SOut or, if SOut==NULL, in a new
* allocated string and returns it
* else if SOut!=NULL
* then copies SIn into SOut and returns SOut
* else returns duplicated SIn
* else returns NULL
=*===================================================================*/
char *exphome(char *SOut, char *SIn)
{char *Rt= NULL;
char *envhome= NULL;
if(SIn)
if(*SIn=='~' && (envhome=getenv("HOME")))
{Rt= malloc(strlen(SIn)+strlen(envhome)+1);
strcpy(Rt, envhome); strcat(Rt, SIn+1);
if(SOut) {strcpy(SOut, Rt); free(Rt); Rt= SOut;}
}
else if(SOut) {strcpy(SOut, SIn); Rt= SOut;}
else Rt= strdup(SIn);
return Rt;
} /*exphome*/
and then
fopen(exphome(NULL, yourfile), ...)
It looks like the answers have prompted edits of original problem. However, as it is currently written there is NO extension on the file name? Is this really true? or does the file end in "*.txt" etc.?
Double-check that you have the correct full file path. Go to the file, right-click on it and select "properties". Are you entering in the path exactly as it is shown, including any suffixes? I.e. if the file is called "file.txt", make sure you include the ".txt" suffix in your code.
i created a text file in d: drive named abc. I am unable to open it. Please tell me how to do so.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
FILE *fp;
clrscr();
fp = fopen("D:/abc.txt","r");
if(fp == NULL)
{
printf("\nCannot open");
getch();
exit(1);
}
fclose(fp);
getch();
}
You have a typo, try
fp = fopen("D:\\abc.txt","r");
instead.
Or if the file is in the same folder as the program:
fp = fopen("abc.txt","r");
correct the path, it should be "D:\\abc.txt"
You file-path looks a little bit strange. Change it to
fp = fopen("D:\\abc.txt","r");
This might work.
Apart from that, include <errno.h> and check for it, if it has failed.
fp = fopen("D:/abc.txt","r");
should be
fp = fopen("D:\\abc.txt","r");
in use \ in path instead of / in Windows and extra \ for escape sequence.
EDIT:
As you commented to others answers that fp = fopen("D:\\abc.txt","r"); also not working then check what is name actually. You might given probably wrong name by mistake, check whether you have error like this.
(1) open command prompt
(2) use DIR command to print name of file:
c:\Users\name> D:
D:\> DIR
Volume in drive D is FUN BOX
Volume Serial Number is B48A-3CE7
Directory of d:\
27-02-2013 19:23 0 abc.txt.txt
26-02-2013 22:05 <DIR> BOLLYWOOD MOVIES
27-02-2013 19:31 0 x
2 File(s) 0 bytes
1 Dir(s) 11,138,654,208 bytes free
file name is abc.txt.txt but when you see this in folder extension doesn't appears and file name looks abc.txt
I am Linux user and I normally do this mistake in Windows. That's why. May be it help you!
If you are working with TurboC put that file in the BIN directory of TC.
And specify the path as fp = fopen("abc.txt","r"); instead of any other alternate path.
The Next time , try to make the error more specific by using perror() function.
Perror() will interpret the error code , this will help you to waste less time , trying to find the type of error.
add this in your code...
if(fp == NULL)
{
perror(fp);
}
On running i got the perror message
No such file or directory.
(since i ran the program , and tried to read a file , without creating it first)
See , if this was the same problem , in your case
I'm trying to open a simple .rtf file called test in C. I'm using Xcode. My code is:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, const char * argv[]) {
FILE *filePtr;
filePtr = fopen("test.rtf", "r");
if (filePtr == NULL) {
fprintf(stderr, "Can't open \"test\"\n");
exit(EXIT_FAILURE);
}
else {
printf("File open successful\n");
int x;
/* read one character at a time until EOF is reached */
while ((x = fgetc(filePtr)) != EOF) {
printf("%c", x);
}
}
fclose(filePtr);
return 0;
}
I have the test.rtf file in the same directory as my Xcode.proj directory. My output is "File open successful", however I do not get anything read from the file. Am I doing this right? Thanks.
There's nothing wrong with that code at all. I tested it (albeit not in Xcode) with a file and the transcript was:
pax> echo hello >test.rtf
pax> ./qq.exe
File open successful
hello
So the obvious think to ask is what happens when you examine test.rtf? Does it actually have any content? Because, when I do:
pax> rm test.rtf ; touch test.rtf
pax> ./qq.exe
File open successful
I get the same behaviour you observe.
Also try renaming it to test2.rtf temporarily and make sure you get the error. It's possible it may be opening a different copy of the file than what you think (this often happens in Visual C since the directory the program runs in is not always what developers think at first).
It looks right.
As for the lack of output, two possibilities:
Are you sure the file has some content? Maybe ls -l test.rtf or dir test.rft
Possibly it has some control characters which cause the terminal to which it is written to suppress output.
Try moving test.rtf to your build directory. If your project is named MyProject, move it to MyProject/build/Debug/.
I can think of two things that could cause this problem. Either there is an error when calling fgetc, or you are getting output that you don't recognize.
fgetc() will return EOF when the end of the file is reached, or an error occurs. To determine if it's an error, just after your while loop try:
if (ferror(filePtr) != 0) printf("error: %d.\n", errno);
A .rtf file is not a plain text file. It likely contains a bunch of formatting information. You are expecting to see "Hello . . . ". but what you may actually see is something like:
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf250
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040
\f0\fs24 \cf0 Hello . . .
And you are just assuming that is GDB output, not your program's output.
Based upon your recent comments, I think you have an empty file test.rtf in the directory your program is run in, and your real test.rtf file is in some other directory. Maybe your fopen() call at some point was fopen("test.rtf", "w"); instead of fopen("test.rtf", "r");, and you later modified it.
To see the directory your program is running in, add the following to your program after the FILE *filePtr; line:
char pwd[512];
if (getcwd(pwd, sizeof pwd) != -1)
printf("In directory %s\n", pwd);
else
fprintf(stderr, "Need bigger buffer, change '512' above\n");
Then, you can open a terminal, do cd <directory>, and test for yourself if the file you want is the file your program is opening.
You probably want this file to be plain text, not rich text. Rich text has a lot of formatting encoded into the file.