程序复制文件不正确

时间:2015-02-28 20:06:51

标签: c file copy

因此,对于我的Systems类中的赋值,我们必须创建一个程序,该程序接收给定源中的文件,并使用三个copyfile()函数之一将其复制到给定目标。

在命令行中运行程序时,它将接受三个参数:./ .cptest,输入文件位置和输出文件位置,以及两个可选参数:copyfile()函数的编号想要使用以及缓冲区大小。

如果为copyfile()函数参数选择1,程序应使用格式化的I / O(文件句柄)复制文件,然后一次复制文件一个字符。

如果为copyfile()函数参数选择2,则程序应使用整数文件描述符复制文件,然后一次复制文件一个字符。

如果为copyfile()函数参数选择3,程序应该分配一个大小等于你为缓冲区大小参数(比如1024)放入的大小的缓冲区,然后使用read()从输入中读取一次最多提交那么多字节。

如果你没有输入第三个参数(copyfile()函数编号),那么程序会自动使用copyfile3()和你用第四个参数决定的缓冲区大小。

如果你没有输入第四个参数(缓冲区大小),那么程序默认将它设置为1024并在必要时使用它(copyfile1()或2()不需要它。)

在调用每个copyfile()函数之前和之后,程序使用gettimeofday()来创建时间戳。然后程序创建一个新的时间戳,以使用后时间戳和前一个时间戳之间的秒和微秒的差异来查找复制所花费的时间,然后打印出所有这些信息。

例如,如果我放入:./cptest~ / My_Documents / photo.JPG~ / assig6 / photo.JPG 3 该计划应该返回:

复制前的时间戳:  秒:1425150842,微秒:914511 复制后的时间戳:  秒:1425150842,微秒:927662 复制需要0秒,13151微秒

现在您已经知道该计划的作用,让我们来解决这个问题。每次我用任何copyfile()函数运行程序时,无论是1,2或3,从技术上讲,复制工作正常,文件最终在正确的目的地,程序返回所有正确的信息时间戳的条款。

然而,实际上,它不起作用,因为当我使用copyfile1()时,它会复制所有字节,但是当我尝试打开文件时 - 比如说.jpg - 它说它可以' t查看该文件,因为它似乎已损坏,损坏或太大。当我使用copyfile2()和copyfile3()时,目标中的文件只有1 KB,当我没有传入第三个或第四个参数时,输出文件有0 KB。 Word文档也是如此。

是否有理由将文件复制好但文件在此过程中损坏?似乎代码是正确的,但最终结果却不是。

这是主文件cptest.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include "cptest.h"

/** cptest.cpp
 * A file copying program.
 * Derived partially from caesar.cpp by Horstmann and Budd from big C++
 */

/** Prints usage instructions.
 * @param program_name the name of this program
 */
void usage(char* program_name) {  
  // Prints out usage instructions if incorrect number of parameters is passed in
  printf("Usage: %s infile outfile copy_function_number buffer_size \n", program_name);
}

/** Prints file opening error message
 * @param filename the name of the file that could not be opened
 */
void open_file_error(char* filename) {  
  // Error message if unable to open the file
  printf("Error opening file %s\n", filename);
}

/** Main program: copies a file.
 * @param argc Number of command-line arguments (including program name).
 * @param argv Array of pointers to character arays holding arguments.
 * @return 0 if successful, 1 if failure.
 */
int main(int argc, char* argv[]) {  
  char* infilename; // Name of input file
  char* outfilename; // Name of output file
  int copy_function_number; // Chooses which copy function is used based on argv[3]
  int buffer_size; // Size of buffer
  int returnstatus; // 0 or 1 depending on success or failure to copy the file to the destination
  struct timeval* before = malloc(sizeof(struct timeval)); // Struct for time before copying is done
  struct timeval* after = malloc(sizeof(struct timeval)); // Struct for time after copying is done

  if (argc != 3 && argc != 4 && argc != 5) {
    usage(argv[0]); // Must have 2, 3, or 4 arguments in addition to ./cptest.
    return 1; // Failure!
  }

  infilename = argv[1]; // Sets first parameter to the input file name
  outfilename = argv[2]; // Sets second parameter to the output file name

  if(argv[3] == NULL) {
    copy_function_number = 3; // Program uses copyfile3 if no third parameter is entered
  }

  else {
    copy_function_number = atoi(argv[3]); // Otherwise program uses whatever function is passed by third parameter
  }

  if (argv[4] == NULL) {
    buffer_size = 1024; // Sets buffer size to 1024 if no fourth parameter is entered
  }

  else {
    buffer_size = atoi(argv[4]); // Otherwise buffer size is whatever user enters as fourth parameter
  }

  if (copy_function_number == 1) {
    gettimeofday(before, NULL); // Get timestamp before the copying
    // Perform the copying with copyfile1() if the third parameter is 1
    returnstatus = copyfile1(infilename, outfilename); 
    gettimeofday(after, NULL); // Get timestamp after the copying
  }

  if (copy_function_number == 2) {
    gettimeofday(before, NULL); // Get timestamp before the copying
    // Perform the copying with copyfile2() if the third parameter is 2
    returnstatus = copyfile2(infilename, outfilename);  
    gettimeofday(after, NULL); // Get timestamp after the copying
  }

  if (copy_function_number == 3) {
    gettimeofday(before, NULL); // Get timestamp before the copying
    // Perform the copying with copyfile3() if the third parameter is 3
    returnstatus = copyfile3(infilename, outfilename, buffer_size);  
    gettimeofday(after, NULL); // Get timestamp after the copying
  }

  else {
    if (copy_function_number != 1 || copy_function_number != 2 || copy_function_number != 3 || argv[3] == NULL) {
      gettimeofday(before, NULL); // Get timestamp before the copying
      // Perform the copying with copyfile3() if no third parameter is entered
      returnstatus = copyfile3(infilename, outfilename, buffer_size);  
      gettimeofday(after, NULL); // Get timestamp after the copying
    }
  }

  struct timeval *copytime = difference_in_time(before, after); // Struct for time after copying is done

  // Print out information of the timestamp before copying
  printf("Timestamp Before Copying: \n Seconds: %d, Microseconds: %d\n", before->tv_sec, before->tv_usec);
  // Print out information of the timestamp after copying
  printf("Timestamp After Copying: \n Seconds: %d, Microseconds: %d\n", after->tv_sec, after->tv_usec);
  // Print out information of the difference between the timestamps (how long the copying took)
  printf("Copying took %d seconds, %d microseconds\n", copytime->tv_sec, copytime->tv_usec);

  return returnstatus; // 0 if successful copy, 1 if unsuccessful.
}

/** Copies one file to another using formatted I/O, one character at a time.
 * @param infilename Name of input file
 * @param outfilename Name of output file
 * @return 0 if successful, 1 if error.
 */
int copyfile1(char* infilename, char* outfilename) {
  FILE* infile; //File handle for source.
  FILE* outfile; // File handle for destination.

  infile = fopen(infilename, "r"); // Open the input file.
  if (infile == NULL) {
    open_file_error(infilename); // Error message if there was a problem opening the input file.
    return 1; // Failure!
  }

  outfile = fopen(outfilename, "w"); // Open the output file.
  if (outfile == NULL) {
    open_file_error(outfilename); // Error message if there was a problem opening the output file.
    return 1; // Failure!
  }

  int intch;  // Character read from input file. must be an int to catch EOF.
  unsigned char ch; // Character stripped down to a byte.

  // Read each character from the file, checking for EOF.
  while ((intch = fgetc(infile)) != EOF) {
    ch = (unsigned char) intch; // Convert to one-byte char.
    fputc(ch, outfile); // Write out.
  }

  fclose(infile); // Close the input file.
  fclose(outfile); // Close the output file.

  return 0; // Success!
}

/** Copies one file to another using integer file descriptors instead of file handles, one character at a time.
 * @param infilename Name of input file
 * @param outfilename Name of output file
 * @return 0 if successful, 1 if error.
 */
int copyfile2(char* infilename, char* outfilename) {
  int infile; //File handle for source.
  int outfile; // File handle for destination.
  // Allocates a buffer for the chars that will be read from the input and written to the output.
  char buffer[1024]; 

  infile = open(infilename, O_RDONLY); // Open the input file.
  if (infile < 0) {
    open_file_error(infilename); // Error message if there was a problem opening the input file.
    return 1; // Failure!
  }

  outfile = open(outfilename, O_WRONLY | O_CREAT); // Open the output file.
  if (outfile < 0) {
    open_file_error(outfilename); // Error message if there was a problem opening the output file.
    return 1; // Failure!
  } 

  int intchin;  // Character read from input file. must be an int to catch EOF.
  int intchout; // Character written to the output file. must be an int to catch EOF.
  // Size of the buffer so that when you are copying extremely large files, it does not have to go through 200000 loop iterations
  int buffer_size = 1024; 
  unsigned char ch; // Character stripped down to a byte.

  // Read each character from the file, checking for 0.
  while ((intchin = read(infile, buffer, buffer_size)) != 0) {
    ch = (unsigned char) intchin; // Convert to one-byte char.
    intchout = write(outfile, buffer, ch); // Write out.
  }

  close(intchin); // Close the input file.
  close(intchout); // Close the output file.

  return 0; // Success!
}

/** Copies one file to another using integer file descriptors, buffer_size characters at a time.
 * @param infilename Name of input file
 * @param outfilename Name of output file
 * @param buffer_size Size of the buffer for reading and writing
 * @return 0 if successful, 1 if error.
 */
int copyfile3(char* infilename, char* outfilename, int buffer_size) {
  int infile; //File handle for source.
  int outfile; // File handle for destination.
  // Allocates a buffer of size buffer_size for the chars that will be read from the input and written to the output.
  char* buffer = (char*) malloc(sizeof(char)* buffer_size); 

  infile = open(infilename, O_RDONLY); // Open the input file.
  if (infile < 0) {
    open_file_error(infilename); // Error message if there was a problem opening the input file.
    return 1; // Failure!
  } 

  outfile = open(outfilename, O_WRONLY | O_CREAT); // Open the output file.
  if (outfile < 0) {
    open_file_error(outfilename); // Error message if there was a problem opening the output file.
    return 1; // Failure!
  } 

  int intchin;  // Character read from input file. must be an int to catch EOF.
  int intchout; // Character written to the output file. must be an int to catch EOF.
  unsigned char ch; // Character stripped down to a byte.

  // Read each character from the file, checking for 0.
  while ((intchin = read(infile, buffer, buffer_size)) != 0) {
    ch = (unsigned char) intchin; // Convert to one-byte char.
    intchout = write(outfile, buffer, ch); // Write out.
  }

  close(intchin); // Close the input file.
  close(intchout); // Close the output file.
  free(buffer); // Free the buffer that was allocated.

  return 0; // Success!
}

/** Makes a new timeval struct that determines the difference between two timestamps
 * @param time1 Struct containing the information for the first timestamp
 * @param time2 Struct containing the information for the second timestamp
 * @return The struct made using the two parameters
 */
struct timeval* difference_in_time(struct timeval* time1, struct timeval* time2) {
  struct timeval* copytime = malloc(sizeof(struct timeval)); // Allocates a struct to hold the difference between the two timestamps.

  if ((time2->tv_sec - time1->tv_sec) < 0) {  
    // Error message for if the first timestamp entered was before the second timestamp.
    printf("Seconds value is negative! time1 should be before time2!\n"); 
  }

  if ((time2->tv_usec - time1->tv_usec) < 0) {
    // Handles if the difference in microseconds between the second and first timestamps would be negative, subtracting 1 from the seconds.
    copytime->tv_sec = (time2->tv_sec - time1->tv_sec) - 1; 
    // Handles if the difference in microseconds between the second and first timestamps would be negative, subtracting the difference from 1000000.
    copytime->tv_usec = 1000000 - (time2->tv_usec - time1->tv_usec); 
  }

  else {
    // Otherwise the seconds for the third timestamp is the difference between the seconds of the second and first timestamps.
    copytime->tv_sec = (time2->tv_sec - time1->tv_sec); 
    // Otherwise the microseconds for the third timestamp is the difference between the microseconds of the second and first timestamps.
    copytime->tv_usec = (time2->tv_usec - time1->tv_usec); 
  }

  return copytime; // Return the new timestamp created.
}

这里是头文件cptest.h:

#ifndef CPTEST_H
#define CPTEST_H

// function prototypes
void usage(char* program_name);
void open_file_error(char* filename);
int copyfile1(char* infilename, char* outfilename);
int copyfile2(char* infilename, char* outfilename);
int copyfile3(char* infilename, char* outfilename, int buffer_size);
struct timeval* difference_in_time(struct timeval* time1, struct timeval* time2);

#endif

这是makefile:

cptest: cptest.o
    gcc -g cptest.o -o cptest

cptest.o: cptest.c cptest.h
    gcc -c -g cptest.c

clean:
    rm -f *.o cptest

docs:
    doxygen
    chmod a+r html/*
    cp -p html/* ~/public_html/cs2303assig6

编辑:认为使用我们需要包含的readme.txt作为示例向您展示会发生什么可能更容易。将其缩短为有用的信息,因此您不必通过更多的文本墙。

原件:

Name: *My name*
Section: CS2303 C01

What Program Does: *Explanation of what program does*

Example: *Example of what should show up when running program in the command line*

Results: *Test data for time it took for each function and using different buffer sizes to find most efficient function and buffer size*

Compiling:

To compile the code, use 'make' in the command line. The makefile should already link all of the .o files to the executable, so the work is done for you.

使用copyfile1()时的结果:

so the work is done for you.S2303 C01

What Program Does: *Explanation of what program does*

Example: *Example of what should show up when running program in the command line*

Results: *Test data for time it took for each function and using different buffer sizes to find most efficient function and buffer size*

Compiling:

To compile the code, use 'make' in the command line. The makefile should already link all of the .o files to the executable, so the work is done for you.

使用copyfile2()和3()时的结果:

so the work is done for you.

1 个答案:

答案 0 :(得分:0)

copyfile2和3完全被破坏,因为它们将读取的字符数转换为char。由于缓冲区大小通常为1024,因此此强制转换结果为0,因此不会写入任何内容。

对于copyfile 1,我建议打开带有二进制标志(“rb”或“wb”)的文件,尽管我不相信这是问题所在。