Попробованное и истинное простое копирование файла кодирует в C?

Угловая JS предоставляет эту функциональность в директиве ng-class . В котором вы можете поставить условие, а также назначить условный класс. Вы можете достичь этого двумя разными способами.

Тип 1

В этом классе кода будет применяться в соответствии со значением значения состояния

, если состояние значение равно 0, тогда примените класс 1

, если значение состояния равно 1, затем примените класс 2

, если значение состояния равно 2, затем примените класс три


Тип 2

В каком классе будет применяться значение статуса

, если значение состояния равно 1 или true, тогда он добавит класс test_yes

, если статус значение равно 0 или false, то он добавит класс test_no

9
задан Eugene Bujak 17 June 2009 в 13:06
поделиться

7 ответов

Что касается фактического ввода-вывода, то код, который я писал миллион раз в различных формах для копирования данных из одного потока в другой, выглядит примерно так. Он возвращает 0 в случае успеха или -1 при установке errno в случае ошибки (в этом случае могло быть скопировано любое количество байтов).

Обратите внимание, что для копирования обычных файлов вы можете пропустить EAGAIN, поскольку обычные файлы всегда блокировка ввода / вывода. Но неизбежно, если вы напишете этот код, кто-то будет использовать его для других типов файловых дескрипторов, так что считайте это халявой.

GNU cp делает оптимизацию для конкретных файлов, чего я не делал. беспокоило здесь, что для длинных блоков по 0 байтов вместо записи вы просто расширяете выходной файл, ища конец.

void block(int fd, int event) {
    pollfd topoll;
    topoll.fd = fd;
    topoll.events = event;
    poll(&topoll, 1, -1);
    // no need to check errors - if the stream is bust then the
    // next read/write will tell us
}

int copy_data_buffer(int fdin, int fdout, void *buf, size_t bufsize) {
    for(;;) {
       void *pos;
       // read data to buffer
       ssize_t bytestowrite = read(fdin, buf, bufsize);
       if (bytestowrite == 0) break; // end of input
       if (bytestowrite == -1) {
           if (errno == EINTR) continue; // signal handled
           if (errno == EAGAIN) {
               block(fdin, POLLIN);
               continue;
           }
           return -1; // error
       }

       // write data from buffer
       pos = buf;
       while (bytestowrite > 0) {
           ssize_t bytes_written = write(fdout, pos, bytestowrite);
           if (bytes_written == -1) {
               if (errno == EINTR) continue; // signal handled
               if (errno == EAGAIN) {
                   block(fdout, POLLOUT);
                   continue;
               }
               return -1; // error
           }
           bytestowrite -= bytes_written;
           pos += bytes_written;
       }
    }
    return 0; // success
}

// Default value. I think it will get close to maximum speed on most
// systems, short of using mmap etc. But porters / integrators
// might want to set it smaller, if the system is very memory
// constrained and they don't want this routine to starve
// concurrent ops of memory. And they might want to set it larger
// if I'm completely wrong and larger buffers improve performance.
// It's worth trying several MB at least once, although with huge
// allocations you have to watch for the linux 
// "crash on access instead of returning 0" behaviour for failed malloc.
#ifndef FILECOPY_BUFFER_SIZE
    #define FILECOPY_BUFFER_SIZE (64*1024)
#endif

int copy_data(int fdin, int fdout) {
    // optional exercise for reader: take the file size as a parameter,
    // and don't use a buffer any bigger than that. This prevents 
    // memory-hogging if FILECOPY_BUFFER_SIZE is very large and the file
    // is small.
    for (size_t bufsize = FILECOPY_BUFFER_SIZE; bufsize >= 256; bufsize /= 2) {
        void *buffer = malloc(bufsize);
        if (buffer != NULL) {
            int result = copy_data_buffer(fdin, fdout, buffer, bufsize);
            free(buffer);
            return result;
        }
    }
    // could use a stack buffer here instead of failing, if desired.
    // 128 bytes ought to fit on any stack worth having, but again
    // this could be made configurable.
    return -1; // errno is ENOMEM
}

Чтобы открыть входной файл:

int fdin = open(infile, O_RDONLY|O_BINARY, 0);
if (fdin == -1) return -1;

Открытие выходного файла - это хитрость. В качестве основы вы хотите:

int fdout = open(outfile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0x1ff);
if (fdout == -1) {
    close(fdin);
    return -1;
}

Но есть мешающие факторы:

  • вам нужен особый случай, когда файлы одинаковы, и я не могу вспомнить, как это сделать переносимо.
  • если выходным именем файла является каталог , вы можете скопировать файл в каталог.
  • если выходной файл уже существует (откройте с помощью O_EXCL, чтобы определить это и проверить наличие EEXIST при ошибке), вы можете сделать что-то другое, например cp - i делает.
  • вы можете захотеть, чтобы разрешения выходного файла отражали разрешения входного файла.
  • вы можете захотеть скопировать другие метаданные, зависящие от платформы.
  • вы можете или можете не желать отключать выходной файл при ошибке.

Очевидно, ответы на все эти вопросы могут быть такими же, как cp ». В этом случае ответ на исходный вопрос: "

3
ответ дан 4 December 2019 в 15:24
поделиться

Принятый ответ, записанный Steve Jessop, не отвечает на первую часть вопроса, Jonathan Leffler делают это, но делают это неправильно: код должен быть написан как

while ((n = fread(buffer, 1, sizeof(buffer), f1)) > 0)
    if (fwrite(buffer, n, 1, f2) != 1)
        /* we got write error here */

/* test ferror(f1) for a read errors */

Объяснение:

  1. sizeof (символ) = 1 по определению, всегда: не имеет значения, сколько битов в нем, 8 (в большинстве случаев), 9, 11 или 32 (на некотором DSP, например) — размер символа тот. Отметьте, это не ошибка здесь, а дополнительный код.
  2. fwrite функционируют записи [до 112] nmemb (второй аргумент) элементы указанного размера (третий аргумент), он не делает требуемый записать точно nmemb элементы. Для фиксации этого, необходимо записать остальную часть крытых тростником данных или просто записать один , элемент размера n — позволил fwrite сделать всю его работу. (Этот объект рассматриваем, должен fwrite писать все данные или нет, но в моей версии короткие записи, невозможные, пока ошибка не происходит.)
  3. необходимо протестировать на чтение ошибки также: просто протестируйте ferror (f1) в конце цикла.

Примечание, вероятно, необходимо отключить буферизацию на обоих входных и выходных файлах для предотвращения трижды буферизации: сначала на чтении к буферу f1, второму в нашем коде, трети на записи к буферу f2:

setvbuf(f1, NULL, _IONBF, 0);
setvbuf(f2, NULL, _IONBF, 0);

(Внутренние буферы должны, вероятно, иметь размер BUFSIZ.)

0
ответ дан 4 December 2019 в 15:24
поделиться

Это функция, которую я использую, когда мне нужно скопировать из одного файла в другой - с тестовой системой:

/*
@(#)File:           $RCSfile: fcopy.c,v $
@(#)Version:        $Revision: 1.11 $
@(#)Last changed:   $Date: 2008/02/11 07:28:06 $
@(#)Purpose:        Copy the rest of file1 to file2
@(#)Author:         J Leffler
@(#)Modified:       1991,1997,2000,2003,2005,2008
*/

/*TABSTOP=4*/

#include "jlss.h"
#include "stderr.h"

#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_fcopy_c[] = "@(#)$Id: fcopy.c,v 1.11 2008/02/11 07:28:06 jleffler Exp $";
#endif /* lint */

void fcopy(FILE *f1, FILE *f2)
{
    char            buffer[BUFSIZ];
    size_t          n;

    while ((n = fread(buffer, sizeof(char), sizeof(buffer), f1)) > 0)
    {
        if (fwrite(buffer, sizeof(char), n, f2) != n)
            err_syserr("write failed\n");
    }
}

#ifdef TEST

int main(int argc, char **argv)
{
    FILE *fp1;
    FILE *fp2;

    err_setarg0(argv[0]);
    if (argc != 3)
        err_usage("from to");
    if ((fp1 = fopen(argv[1], "rb")) == 0)
        err_syserr("cannot open file %s for reading\n", argv[1]);
    if ((fp2 = fopen(argv[2], "wb")) == 0)
        err_syserr("cannot open file %s for writing\n", argv[2]);
    fcopy(fp1, fp2);
    return(0);
}

#endif /* TEST */

Очевидно, что эта версия использует файловые указатели из стандартного ввода-вывода, а не файловые дескрипторы , но он достаточно эффективен и настолько портативен, насколько это возможно.


Ну, кроме функции ошибок - это свойственно мне. Если вы чисто обрабатываете ошибки, все должно быть в порядке. Заголовок "jlss.h" объявляет fcopy () ; заголовок "stderr.h" объявляет err_syserr () среди многих других подобных функций сообщения об ошибках. Далее следует простая версия функции - настоящая добавляет имя программы и выполняет некоторые другие действия.

#include "stderr.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

void err_syserr(const char *fmt, ...)
{
    int errnum = errno;
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
    exit(1);
}

Приведенный выше код можно рассматривать как имеющий современную лицензию BSD или GPL v3 по вашему выбору.

5
ответ дан 4 December 2019 в 15:24
поделиться

Here is a very easy and clear example: Copy a file. Since it is written in ANSI-C without any particular function calls I think this one would be pretty much portable.

1
ответ дан 4 December 2019 в 15:24
поделиться

Одна вещь, которую я обнаружил при реализации моей собственной копии файла, кажется очевидной, но это не так: операции ввода-вывода медленные . Вы можете в значительной степени измерить скорость вашей копии по тому, сколько из них вы сделаете. Поэтому очевидно, что вам нужно сделать как можно меньше из них.

Наилучшие результаты, которые я обнаружил, были, когда я взял себе великолепный буфер, прочитал в него весь исходный файл за один ввод-вывод, а затем записал весь буфер обратно. его в одном вводе-выводе. Если бы мне даже приходилось делать это 10 партиями, это делалось очень медленно. Пытаться прочитать и записать каждый байт, как наивный программист может попытаться сделать это первым, было просто болезненно.

1
ответ дан 4 December 2019 в 15:24
поделиться

Depending on what you mean by copying a file, it is certainly far from trivial. If you mean copying the content only, then there is almost nothing to do. But generally, you need to copy the metadata of the file, and that's surely platform dependent. I don't know of any C library which does what you want in a portable manner. Just handling the filename by itself is no trivial matter if you care about portability.

In C++, there is the file library in boost

1
ответ дан 4 December 2019 в 15:24
поделиться

размер каждого чтения должен быть кратен 512 (размер сектора) 4096 - хороший вариант

2
ответ дан 4 December 2019 в 15:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: