Home > Mobile >  (Using C): Accessing each file in a directory and editing its contents, one by one
(Using C): Accessing each file in a directory and editing its contents, one by one

Time:03-06

I am a beginner programmer (learning how to use things like hash tables and tries at present) and so am not well informed, and would value your advice.

I want to write a program that:

  1. Receives a directory address as an argv.
  2. Goes through each file in that directory, one by one (they will all be BMPs) and after reading to a buffer...
  3. Performs a function on the RGB values in that buffer, nothing special -- imagine something like a box blur or a greyscale function.
  4. Saves the buffer to a file in a new folder, closes the file in the original directory currently being accessed, and moves onto the next one until it reaches the final file.

I am experimenting with dirent as best I can, but no matter how I phrase this question, I end up with something that tells me how to read filenames and list them, and how to read those into a dirent struct that doesn't itself hold the file data; I get nothing about specifically accessing a directory and looking for files within them with the explicit purpose of fopen()ing them.

An excerpt of my code, to give you an example of my (probably awful) logic:

DIR *folder;
folder = opendir(argv[3]);
if (folder == NULL);
{
    printf("Unable to read folder");
    return 2;
}

struct dirent *input;
FILE *fileinput;
int files = 0;

// Use this file loop to go through each 
while(   (input = readdir(folder)) != NULL  )
{
    fileinput = fopen(input->d_name, "r");
    if (filepointer != NULL)
    {
        // checks for file headers, open another FILE for writing, my actual function etc.
    }

But again, it seems that the FOPEN there is accessing a copy of a name, and not the file itself indicated so. And I simply don't have the vocabulary to find a similar question answering this, on SO or elsewhere.

Would anyone mind pointing me in the right direction? Apologies for any hassle as I'm sure this is a very basic question...

ーーーーEDIT: requested to post updated code for review:

#include <dirent.h> //必要
#include <sys/types.h>
#include "helpers.h" //bmp.h declared within
#include <getopt.h> //parse argvs

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <math.h>
#include <string.h>

const int PATH_MAX = 260;

int main(int argc, char *argv[])
{
    char *filters = "rbg";

    char filter = getopt(argc, argv, filters);
    if (filter == '?') {
        printf("Invalid filter.\nUsage: ./colourfilter [flag]\n r = red\t b = blue\t g = green\n");

        return 2;
    }
    if (getopt(argc, argv, filters) != -1) {
        printf("Only one filter may be used.\n");
        return 3;
    }

    // OPEN INPUT FOLDER
    const char *inputs = "inputs";
    DIR *infolder = opendir(inputs);

    if (infolder == NULL) {
        //fprintf(stderr,"Unable to read folder %s\n", infolder);
        printf("Unable to read folder.\n");
        return 4;
    }
    
    // Declare variables
    struct dirent *input;
    int counter = 0;
    char name[8];
    FILE *imgout;

    while((input = readdir(infolder)) != NULL) 
    {
        char path[PATH_MAX];
        if (!strcmp(input->d_name, ".") || !strcmp(input->d_name, "..")) {
            continue;
            
        }

  
        if ((size_t)snprintf(path, sizeof(path), "%s/%s", infolder, input->d_name) >= sizeof(path)) {
            printf("Filename too long: %s/%s\n", infolder, input->d_name);
            continue;
        } 

        // FOPEN THINGS
        // "Also make sure you open the BMP files as binary with "rb" and "wb".:" (see: https://stackoverflow.com/questions/71321367/)
        
        sprintf(name, "i.bmp", counter);
        FILE *imgin = fopen(path, "rb");
              imgout = fopen(name, "wb");
        
        if (imgin == NULL) {
            printf("Could not open %s.\n", path);
            return 7;
        }
        if (imgout == NULL) {
            fclose(imgin);
            printf("Could not create images.\n");
            return 8;
        }
    
        BITMAPFILEHEADER bf;
        fread(&bf, sizeof(BITMAPFILEHEADER), 1, imgin);

        BITMAPINFOHEADER bi;
        fread(&bi, sizeof(BITMAPINFOHEADER), 1, imgin);

        // Ensure infile is (likely) a 24-bit uncompressed BMP 4.0
        if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
            bi.biBitCount != 24 || bi.biCompression != 0)
        {
            fclose(imgout);
            fclose(imgin);
            printf("Unsupported file format.\n");
            return 8;
        } // ... other stuff after this for implementing functions etc.

CodePudding user response:

The problem is fopen(input->d_name, "r"); tries to open the file in the current directory instead of the one specified in folder. You must construct the path to the file.

Also make sure you open the BMP files as binary with "rb" and "wb".

    char *foldername = argv[3];
    DIR *folder = opendir(foldername);
    if (folder == NULL) {
        fprintf(stderr, "Unable to read folder %s\n", foldername);
        return 2;
    }
    
    struct dirent *input;
    FILE *fileinput;
    int files = 0;
    
    // Use this file loop to go through each 
    while ((input = readdir(folder)) != NULL) {
        char path[PATH_MAX];
        if (!strcmp(input->d_name, ".") || !strcmp(input->d_name, "..")) }
            continue;
        }
        if ((size_t)snprintf(path, sizeof path, "%s/%s", foldername, input->d_name) >= sizeof path) {
            fprintf(stderr, "filename too long: %s/%s\n", foldername, input->d_name);
            continue;
        }
        fileinput = fopen(path, "rb");
        ...
  • Related