Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > какие-то проблемы с созданием файлов


Автор: SynthEtic 19.11.2006, 16:49
Постановка задачи: 
грубо говоря: открыть директорию, прочитать все файлы определенного типа и посимвольно переписать их в другую директорию


Попытка решения: 
Я передаю в функцию имя файла, открываю его для чтения, создаю по нужному пути файл для записи, и затем посимвольно читаю/пишу...
но вот странная (для меня) ошибка - прочитываются все файлы полностью и записывается все полностью (проверено по размеру прочитанного и записанного), но: прочитывается 124 файла (как и должно быть), а создается только 36! Причем, самое интересное - то, что многие прочитанные файлы в записанном - сливаются в один! Т.е. в один файл записывается несколько... Привожу куски кода, как я это делаю... оба фрагмента у меня дают одинаковый результат...
Подскажите, в чем ошибка? Вроде все дескрипторы вовремя открываются и закрываются...
Сижу под Suse 10

Код: 

Код

int n;
    int fd_in = open(name.c_str(), O_RDONLY);
    int fd_out = open(out_path.c_str(), O_WRONLY | O_CREAT);
    
    char ch, buf[SIZE];
    
    while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, SIZE);


и так: 

Код

    ifstream in(name.c_str());
    ofstream out(out_path.c_str(), ios::app);
    char ch;
    
    while (!in.eof()) {
        in.get(ch);
                         out.put(ch);
    }
    
    out.close();
    in.close();

Автор: MAKCim 19.11.2006, 17:55
SynthEtic
Код

while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, n);

Автор: MAKCim 19.11.2006, 18:32
Цитата

Код

while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, SIZE);


это копирование файла?

Автор: GrayCardinal 19.11.2006, 21:07
Неплохо бы весь код на бочку. Конкретно в этих отрывках ошибок не вижу.  smile 

Автор: bilbobagginz 20.11.2006, 01:32
да думаю файлы иногда не только открывать надо... но и закрывать тоже..

Автор: kirjanov 20.11.2006, 09:10
зачем O_WRONLY | O_CREAT? O_CREAT создаст дескриптор для записи.
Код

while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, SIZE); //так тут бы лучше и записывать n байт

Автор: MAKCim 20.11.2006, 17:26
Цитата

да думаю файлы иногда не только открывать надо... но и закрывать тоже.. 

Цитата

Подскажите, в чем ошибка? Вроде все дескрипторы вовремя открываются и закрываются...

кроме того по завершении процесса идет вызов exit_files(), которая закрывает все открытые файлы
Цитата

зачем O_WRONLY | O_CREAT? O_CREAT создаст дескриптор для записи.

Цитата

creat() is equivalent to open() with flags equal to O_CREAT | O_WRONLY | O_TRUNC

зачем тогда в man-е написан O_WRONLY

Автор: SynthEtic 21.11.2006, 17:28
MAKCim
Код


while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, SIZE);[code=cpp]

да, это копирование файла
fd_in - дескриптор читаемого файла
fd_out - дескриптор создаваемого файла

buf - массив char, длиной BUFSIZ - константа, определенная в <stdio.h> как оптимальный размер блока для ввода/вывода

kirjanov
я не совсем понял вопрос... зачем я ставлю эти флаги? - чтобы создать файл, если его не существует (а его не существует) и открыть его на запись... O_TRUNC и O_APPEND - не ставлю, так как для меня это не имеет значения - все равно новый файл - пустой, так что, что что транкэйт, что аппенд smile 

bilbobagginz
во втором варианте (с потоками) кода - дескрипторы закрываются smile а в первом - просто не скопировал сюда

GrayCardinal
собсна, это - функция:
Код

void someCopy(string name, string path) {
    int n;
    int fd_in = open(name.c_str(), O_RDONLY);
    int fd_out = open(out_path.c_str(), O_WRONLY | O_CREAT);
    char ch, buf[SIZE];
    
    while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, SIZE);

    close(fd_in);
    close(fd_out);
}


вызываемая внутри другой, которая определяет тип: 
Код

void TypeShow(dirent *dp, off_t size) {
    string file_name = dp->d_name;
    string extention, path;
    int pos = file_name.rfind(".", file_name.size()); 
    extention = file_name.substr(pos+1);
    if (extention == "html" || extention == "htm") {
        cout.setf(ios::left);
        cout.width(10);
        cout<<size<<"\tbytes\t";
        cout.width(30);
        cout<<dp->d_name;
        cout.width(21);
        cout<<"Type: HTML Document\t"<<get_current_dir_name()<<endl;
        html++;
        path = get_current_dir_name();
        someCopy(path, file_name);
            else if (extention == 'jpg')..... /*
                         никакой обработки - только вывод на экран размера и имени
                         и еще для нескольких других типов файлов
            */
}

которая вызывается при обходе директории:
Код

void View(DIR* dirp, char* path) {
    struct stat st;
    struct dirent *dp;
    chdir(path);
    
    for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
        stat(dp->d_name, &st); // получаем имя первого элемента дерева
        // получаем аттрибуты файла
        if (S_ISDIR(st.st_mode)) {
            if (strcmp(dp->d_name, ".") != 0 &&  strcmp(dp->d_name, "..") != 0) {
                // Если файл является директорией, и при этом - не текущая директория
                // и не директория верхнего уровня (..) - показываем имя и входим
                cout<<"DIR\t\t\t"<<dp->d_name<<"\n------------------------------------------contains: "<<endl;
                View(opendir(dp->d_name), dp->d_name);
                chdir("../");
            }
            else    // выводим на экран директории "../" и "./"
                cout<<"DIR\t\t\t"<<dp->d_name<<endl;
        }
        else if (S_ISREG(st.st_mode)) {
            // Если файл - определяем его тип и инкрементируем счетчик файлов
            TypeShow(dp, st.st_size);
            total++;
        }
        // на каждой итерации происходит получение файла - обычного или директории
    }
}

Автор: Ignat 21.11.2006, 18:20
SynthEtic, а что говорит strace по поводу дескрипторов?

Автор: bilbobagginz 21.11.2006, 20:49
та ладно, кроме read и write  иногда и fflush надо делать (хотя-бы в DEBUG версии), для более чувственного отношения к работе:
Код

void someCopy(string name, string path) {
    int n;
    int fd_in = open(name.c_str(), O_RDONLY);
    int fd_out = open(out_path.c_str(), O_WRONLY | O_CREAT);/*что  [***]дь за out_path ты открываешь ?! */
    char ch, buf[SIZE];
    
    while ((n = read(fd_in, buf, SIZE)) > 0)
        write(fd_out, buf, SIZE);
    close(fd_in);
    close(fd_out);
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)