简体   繁体   中英

c programming read() and write() content to file

The user should input some file names in the command line and the program will read each file name from argv[] array. I have to perform error checking etc.

I want to read each filename. For example, if argv[2] is 'myfile.txt', the program should read the content of 'myfile.txt' and store value in char buffer[BUFSIZ] and then write the content of buffer into another file.

However before the content is written, the program should also write the name of the file and the size. Such that the file can be easily extracted later. A bit like the tar function.

The file I write the content of buffer , depending on the number of files added by user, should be a string like:

myfile.txt256Thisisfilecontentmyfile2.txt156Thisisfile2content..............

My question is

1) How do I write value of argv[2] into file using write() statement, as having problems writing char array, what should I put as (sizeof(?)) inside write() . see below as I don't know the length of the file name entered by the user.

2) Do I use the '&' to write an integer value into file after name, for example write 4 bytes after file name for the size of file

Here is the code I have written,

char buffer[BUFSIZ];
int numfiles=5; //say this is no of files user entered at command
open(file.....

lseek(fdout, 0, SEEK_SET); //start begging of file and move along each file some for loop

for(i=0-; ......
//for each file write filename,filesize,data....filename,filesize,data......
int bytesread=read(argv[i],buffer,sizeof(buffer));
write(outputfile, argv[i], sizeof(argv)); //write filename size of enough to store value of filename
write(outputfile, &bytesread, sizeof(bytesread));
write(outputfile, buffer, sizeof(buffer));

But the code is not working as I expected.

Any suggestions?

Since argv consists of null-terminated arrays, the length you can write is strlen(argv[2])+1 to write both the argument and null terminator:

size_t sz = strlen (argv[2]);
write (fd, argv[2], sz + 1);

Alternatively, if you want the length followed by the characters, you can write the size_t itself returned from strlen followed by that many characters.

size_t sz = strlen (argv[2]);
write (fd, &sz, sizeof (size_t));
write (fd, argv[2], sz);

You probably also need to write the length of the file as well so that you can locate the next file when reading it back.

1., You can write the string the following way:

size_t size = strlen(string);
write(fd, string, size);

However, most of the time it's not this simple: you will need the size of the string so you'll know how much you need to read. So you should write the string size too.

2., An integer can be written the following way:

write(fd, &integer, sizeof(integer));

This is simple, but if you plan to use the file on different architectures, you'll need to deal with endianness too.

It sounds like your best bet is to use a binary format. In your example, is the file called myfile.txt with a content length of 256, or myfile.txt2 with a content length of 56, or myfile.txt25 with a content length of 6? There's no way to distinguish between the end of the filename and the start of the content length field. Similarly there is no way to distinguish between the end of the content length and the start of the content. If you must use a text format, fixed width fields will help with this. Ie 32 characters of filename followed by 6 digits of content length. But binary format is more efficient.

You get the filename length using strlen(), don't use sizeof(argv) as you will get completely the wrong result. sizeof(argv[i]) will also give the wrong result.

So write 4 bytes of filename length followed by the filename then 4 bytes of content length followed by the content.

If you want the format to be portable you need to be aware of byte order issues.

Lastly, if the file won't all fit in your buffer then you are stuffed. You need to get the size of the file you are reading to write it to your output file first, and then make sure you read that number of bytes from the first file into the second file. There are various techniques to do this.

thanks for replies guys,

I decided not to use (size_t) structure instead just assigned (int) and (char) types so I know exact value of bytes to read() out. ie I know start at beggining of file and read 4 bytes(int) to get value of lenght of filename, which I use as size in next read()

So, when I am writing (copying file exactly with same name) users inputted file to the output file (copied file) I writing it in long string, without spaces obviously just to make it readable here,

filenamesize filename filecontentsize filecontent ie 10 myfile.txt 5 hello

So when come to reading that data out I start at begining of file using lseek() and I know the first 4 bytes are (int) which is lenght of filename so I put that into value int namelen using the read function.

My problem is I want to use that value read for the filenamesize(first 4 bytes) to declare my array to store filename with the right lenght. How do I put this array into read() so the read stores value inside that char array specified, see below please

int namelen; //value read from first 4 bytes of file lenght of filename to go in nxt read()
char filename[namelen]; 
read(fd, filename[namelen], namelen);//filename should have 'myfile.txt' if user entered that filename

So my question is once I read that first 4 bytes from file giving me lenght of filename stored in namelen, I then want to read namelen amount of bytes to give me the filename of originally file so I can create copied file inside directory?

Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM