gpt4 book ai didi

c - 程序复制文件不正确

转载 作者:行者123 更新时间:2023-11-30 19:44:03 25 4
gpt4 key购买 nike

因此,对于我的 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 - 它说它无法查看文件,因为它似乎已损坏、损坏或太大。当我使用 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.

最佳答案

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

对于副本文件 1,我建议使用二进制标志(“rb”或“wb”)打开文件,尽管我不确信这是问题所在。

关于c - 程序复制文件不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28786276/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com