I am trying to open a file in a subdirectory called "Files". I know how to open a file in a subdirectory if I know the name:
fopen("./Files/file.txt", "r");
However, I am trying to create a file that will open any and all files in the subdirectory without having to know the file names ahead of time. I am using the reaaddir() function to be able to locate the file name, however, I am not sure how to plug it into fopen to open and read the file. The readdir() function automatically saves the file name in dp_>d_name. Then If I do this:
fopen("./Files/dp->d_name", "r");
the program is going to try to open the file named "dp->d_name" rather than the file name stored at that location.
IF there is not a way to do this, is there a way to change the current working directory from within the program? Every file I want to open is within the same subdirectory, so that would be an acceptable solution.
Here is my code, for reference:
#include <stdio.h>
#include <dirent.h>
#include <string.h>
void readFile(int)
{
DIR *dir;
struct dirent *dp;
char * file_name;
char buffer[100];
FILE *out;
FILE *in;
char outName[] = "filenames.txt";
if (( out = fopen(outName, "w+")) == NULL )
{
printf("Can't open %s for writing.\n", outName);
return 2;
}
dir = opendir("./Files/");
while ((dp=readdir(dir)) != NULL)
{
if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
{
//do nothing...
}
else
{
if (( in = fopen( dp->d_name, "r")) == NULL)
{
printf("Can't open %s for writing.\n", dp->d_name);
return 2;
}
fgets(buffer, 100, in);
printf("\"%s\"\n", buffer);
}
}
closedir(dir);
fclose(out);
return 0;
}
you can create the full file location in another variable by joining "./Files/" before dp->d_name. you can either use strcat() for it or use create char* with enough size to store the entire location and then fill it using a for loop, and then use this variable in fopen. eg.
if dp->d_name = "f1.txt" then create a variable,
newFileName = "./Files/f1.txt" and then fopen(newFileName, "r");
Related
Im making a txt editor in the terminal, one of it's features is to edit a specific line.
To do so,
I am creating a new temporary txt file,
deleting the old/original one
and renaming the temporary one to the original.
Here's the code:
FileLineEdit(char filename[20], int line, char newline[1000]){
FILE * fp;
FILE * fptmp;
char buffer[1000];
int count;
int ret;
fp = fopen(filename, "r");
fptmp = fopen("tmp/replace.txt", "w");
if (fp == NULL || fptmp == NULL)
{
printf("\nErro!\n");
exit(1);
}
count = 0;
while ((fgets(buffer, 1000, fp)) != NULL)
{
count++;
if (count == line)
fputs(newline, fptmp);
else
fputs(buffer, fptmp);
}
fclose(fp);
fclose(fptmp);
//strcat(fullpath, filename);
//printf("%s", fullpath);
ret = remove(filename);
if(ret == 0) {
printf("File deleted successfully");
} else {
printf("Error: unable to delete the file");
}
rename("tmp/replace.txt", "tmp/a.txt");
getch();
}
The output is constantly:
Error: unable to delete the file
btw once I try this outside the "tmp/" folder it works just fine
The /tmp folder has the sticky bit (s) set, and that means, that anyone can read and create/modify files in it, but only its owner (root) can remove them.
So, if is what you want your program to do, you should do it in some directory other than /tmp
Also, as jarmod pointed out, you shouldn't have a hardcoded filename for your temporary filename. You should use tmpfile or tmpnam for this purpose:
Instead of:
fptmp = fopen("tmp/replace.txt", "w");
Write:
fptmp = tmpfile();
The file will be automatically deleted when the file stream is closed.
(You can read a more about the /tmp dir here)
I am trying to create a c program that reads the extensions of the files in its current working directory.
The program then creates folders that correspond to the extensions of the files. It then copies each file
from its cwd into the corresponding folder.
e.g:
hello.txt into created .txt folder
The code successfully creates folders for all the file extensions in the current directory, but crashes when it begins to copy.
Here is the whole code.
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <dir.h>
#include <stdlib.h>
#include <errno.h>
int main(void) {
FILE *input, *output; // Two files, input and output
char ch; // ch is used to assign characters from input file which will then be copied into the output file
char *exe = ".exe";
struct dirent *de;
DIR *dr = opendir("."); // Open directory for reading
printf("%s", dr->dd_name);
// If directory doesn't exist, quit
if(dr == NULL) {
printf("Can't open current directory.");
return 0;
}
// Loop first to create a directory corresponding to all
// extensions present in the current directory
while((de = readdir(dr)) != NULL) {
char *filename = de->d_name; // Get the filename
char *ext = strrchr(filename, '.'); // Get the extension
if(!(!ext || ext == filename)){ // Compare extension
int check = mkdir(ext);
if(!check)//Check if the directory was created
printf("Directory created successfully.\n");
else {
printf("Unable to create directory.\n");
}
}
}
// Close the directory so as to reset the pointer ready for the next read.
closedir(dr);
dr = opendir(".");
// Loop reading each file and checking which
// directory it corresponds to.
while((de = readdir(dr)) != NULL) {
char *filename = de->d_name; // Get the filename
char *ext = strrchr(filename, '.'); // Get the extension
if(!(!ext || ext == filename)){ // Check for a valid extension
DIR *file_ext_dir = opendir(ext); // Open the dir that corresponds to the extension of the file.
char *dir_name = file_ext_dir->dd_name; //Get the dir name of the opened directory
if(file_ext_dir && (strcmp(dir_name, "..") != 0)&& (strcmp(ext, exe) !=0) ) { //ignore .exe and the cwd
printf("Successfully opened: %s dir\n", file_ext_dir->dd_name);
char *output_path = strcat(dir_name, filename);
printf("Ready to copy files from %s to: %s\n", filename, output_path);
output = fopen(output_path, "a+"); // Open output.txt for appending, if doesn't exist, create it.
input = fopen(filename, "r"); // Open the input file ()'filename') for reading
while(1) { // Loop through the input file
ch = fgetc(input); // Get the current character
if(ch == EOF) break; // Stop if EOF is found
putc(ch, output); // Put current character from the input file into output.txt
}
fclose(input); // Close input file
fclose(output); // Close output file
closedir(file_ext_dir);
} else if(ENOENT == errno){ //Check if there is no such directory and handle the error
printf("Dir does not exist.");
}else {
continue; //Skip that file if for some reason the directory cannot be opened.
}
}
}
closedir(dr); // Close directory
printf("Created directories and copied all files to that correspond to them.");
return 0;
}
I'm trying to write a program that can open all given files in a directory, and output the files with some changes to another directory given a path specified by the user. I made a function that will be called after fork() for each filename encountered in the current directory, and the output will have the same name in this new directory. I have looked all over, and I still can't find a reason as to why fgets() keeps returning NULL.
void sorter(char *fileName, char *directory, char* newName){
FILE *edit = fopen(fileName, "r");
char buf[700];
char *bufp = buf;
char *fLine = fgets(bufp, sizeof(buf), edit);
if (edit == NULL){
exit(EXIT_FAILURE);
}
printf("%s\n", fLine);
chdir(directory);
FILE *output=fopen(newName, "w");
while(fLine){
fprintf(output, fLine);
fprintf(output, "done");
}
fclose(output);
fclose(edit);
}
I have creates a file in directory and want to read it in. I am using the following code to open and read a file in C-Language. But it creates a new file instead of reading the old file.
int main()
{
FILE * file;
file = fopen ("file", "r+");
//file reading code
fclose(file);
return(0);
}
you are using 'r+' mode to open the file. It creates a new file if not already exist in the directory. see the following code for your help.
int main()
{
FILE * file;
file = fopen ("file", "r");
if(file !== NULL)
// to do file reading code
else
printf("error in reading file");
fclose(file);
return(0);
}
also check the file name that you are using in fopen() function.It is case sensitive and also check the extension of that file e.g; .txt or .data or what ever. e.g;
file = fopen ("File.txt", "r");
If you only intend to read from a file then open it for reading, i.e. mode r (notice no +):
file = fopen ("file", "r");
I agree with answers given but you can also additionally check if file is present or not. Something as below. In case program does not recognize the file it will let you know. Avoid using r+ in case you want to read an already existing file.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch, file_name[25];
FILE *fp;
printf("Enter the name of file you wish to see\n");
gets(file_name);
fp = fopen(file_name,"r"); // read mode
if( fp == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
while( ( ch = fgetc(fp) ) != EOF )
printf("%c",ch);
fclose(fp);
return 0;
}
My program iterates through a single directory (non-recursively) and stores the names of all the files in that directory inside an array. Then, it uses that array in the second part of my program and returns some information about each file. I can iterate through the directory, and I can process a single file, but I'm having trouble combining the two parts of the program. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int getArraySize(char* arr[]);
int getArraySize(char* arr[]) {
return sizeof(&arr);
}
char *filesArray[200];
int main (int argc, char* argv[])
{
DIR *dir;
struct dirent *ent;
int filesCtr = 0;
if ((dir = opendir ("/home/dshah/Documents/CECS 420/Project 3")) != NULL) {
while ((ent = readdir (dir)) != NULL) { /* print all the files and directories within directory */
if (strcmp(ent->d_name, ".") == 0) {
continue;
} else if (strcmp(ent->d_name, "..") == 0) {
continue;
} else if (ent->d_type == 4) { // if a directory
continue;
} else {
filesArray[filesCtr] = ent->d_name;
printf("%s\n", filesArray[filesCtr]);
filesCtr++;
}
}
closedir (dir);
} else { /* could not open directory */
perror ("Could not open directory");
}
int i;
for (i = 0; i < getArraySize(filesArray); i++) {
char* filename = filesArray[i];
FILE *file = fopen (filename, "r");
if (file != NULL) {
char line [128]; /* or other suitable maximum line size */
int ctr = 1;
while (fgets(line, sizeof line, file) != NULL) { /* read a line */
if (strstr(line, "is") != NULL) {
printf("%s:%d:%s", filename, ctr, line);
}
ctr++;
}
fclose (file);
} else {
perror (filename); /* why didn't the file open? */
}
}
return 0;
}
The line I am having trouble with is:
char* filename = filesArray[i];
Is this line of code correct? It works when I set filename to a string like "file.txt", so shouldn't this also work when I do printf("n %s\n", filesArray[i]);? Is filesArray[i] in this line of code a string?
EDIT:
Thanks, that fixed the problem. One more quick question: I'm trying to append the full path on
FILE *file = fopen (filename, "r");`
line by changing it to
FILE *file = fopen (strcat("/home/dshah/Documents/CECS 420/Project 3/", filename), "r");
but it gives me a segmentation fault. Shouldn't this work cause I'm just specifying the path?
When you pass an array to a function, it decays to a pointer, so when you do e.g. &arr you actually get a pointer to that pointer, and the size of a pointer is most likely not the size of the original array. If (and I mean really if) the array is actually a string, you can use strlen to get the length of the string (not including the string terminator character).
In your case, you don't actually need the getArraySize function, as you already have a counter telling you how many strings there is in the filesArray array: The filesCtr variable.
Also, when using a function such as readdir the d_name field of the returned entry may actually be pointing to a static array so you can't really just copy the pointer, you have to copy the complete string. This is done with the strdup function:
filesArray[filesCtr] = strdup(ent->d_name);
Remember that when done you have to free this string.
Oh, and avoid using "magic numbers" in your code, for example when checking if the directory entry is a sub-directory (ent->d_type == 4). Use the macros available to use (end->d_type == DT_DIR).
And a final thing, the d_name field of the readdir entry only contains the actual filename, not the full path. So if you want the full path you have to append the path and the filename.