I've got how to copy one file to another from start, but how could i modify the programme to copy it in reverse order? Source file should have read access and destination file read write execute. I have to use file control libraries.
for example
FILE A File B should be
|---------| |----------|
|ABCDEF | |FEDCBA |
|---------| |----------|
*********************UPDATE**********
Thank you, MikeNakis for hints and suggestions
,Sangeeth for your code
I've reworked the code and now it is copy bytes in reverse order printing filesize
here is the code
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3) {
fprintf(stderr, "usage %s <source> <dest>", argv[0]);
exit(-1);
}
if ((source = open(argv[1], 0400)) < 0) { //read permission for user on source
fprintf(stderr, "can't open source");
exit(-1);
}
if ((dest = creat(argv[2], 0700)) < 0) { //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--) { //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1) {
fprintf(stderr, "can't read 1 byte");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1) {
fprintf(stderr, "can't write 1 byte");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
You just seek to the end and start reading from there. No wonder it won't read anything. You need to seek to the end minus 1 byte, read one byte, write it, then seek to the end minus two bytes, read another byte, and so on.
I presume this is a homework assignment, so your professor should not mind the extreme inefficiency of this approach. (Real-world performance concerns are oh-so un-academic.) If he complains, tell him that in theory, it has the same time complexity as any other algorithm which would perform the same task: O(N). (That's pronounced "big oh of en".) He will give you an A+.
lseek(source, (off_t) i, SEEK_SET); should probably be lseek(source, (off_t) i - 1, SEEK_SET);
Related
Terrible coder here, this program I'm trying is to take user input and return it reversed in a new file. the kicker is using system calls (which I have just been exposed to). I am having trouble with my outputs. May someone please point out the error?
#include <fcntl.h>
#include <stdio.h>
#include "apue.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(){
int fd1;
int fd2;
int offset;
char readc;
char filename[125];
printf("Please enter the file you wish to reverse: ");
scanf("%s", &filename);
fd1 = open(filename, O_RDONLY);
printf("open succesfully! File has been reversed and in a new file\n");
if (fd1 < 0) { perror("Error! Can't open file\n"); exit(1); }
//create a new file
fd2 = open("ReversedFile.txt", O_RDWR | O_CREAT, 0644);
if(fd2 < 0){ perror("Error! Can't open file"); exit(1); }
offset = lseek(fd1, 0, SEEK_END);
while(offset > 0){
read(fd1, &readc, 1);
write(fd2, &readc, 1);
lseek(fd1, -2, SEEK_CUR);
offset--;
}
close(fd1);
close(fd2);
return 0;
}
My first output where foo.txt contained exclamation points (which are invalid i discovered) is:
\00World Hello
!gnidoc ta kcus I
if this is readable i am correct
My second output however without exclamation point is:
圀牯摬䠠汥潬朊楮潤慴欠畣晩琠楨獩爠慥慤汢浡挠牯敲瑣
Why is this happening?
lseek(fd1, 0, SEEK_END) sets the file pointer at the end of the file. Then you try to read one byte which fails precisely because you are already at the end of the file and you don't check if read fails. If you had checked that, you would have found out that read returns 0 (meaning nothing has been read). Then you write the garbage value which is still in readc to the output file.
You want this:
offset = lseek(fd1, -1, SEEK_END); // seek to end of file -1 char
while (offset >= 0) {
int bytesread =read(fd1, &readc, 1);
if (bytesread == 0)
{
perror("something went wrong with read\n");
exit(1);
}
write(fd2, &readc, 1);
lseek(fd1, -2, SEEK_CUR);
offset--;
}
I tried to write basic program in C which copy data from file to another with given source path, destination path and buffer size as input.
my problem is the destination file filled with junk or something because its way larger than the source (get bigger depending on buffer size) and can't be open.
How do i read and write just the bytes in the source?
i'm working in linux, and this is the actually copying part:
char buffer[buffer_size];
int readable=1;
int writeable;
while(readable != 0){
readable = read(sourcef, buffer, buffer_size);
if(readable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not read.");
}
writeable = write(destf, buffer, buffer_size);
if(writeable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not write.");
}
}
writeable = write(destf, buffer, buffer_size);
must be
writeable = write(destf, buffer, readable);
Currently you do not write the number of characters you read but all the buffer, so the output file is too large
You also manage wrongly the end of the input file
The return value of read is :
On success, the number of bytes read is returned (zero indicates end of file)
On error, -1 is returned
A proposal :
/* you already check input and output file was open with success */
char buffer[buffer_size];
for(;;){
ssize_t readable = read(sourcef, buffer, buffer_size);
if(readable <= 0){
close(sourcef);
close(destf);
if (readable != 0)
/* not EOF */
exit_with_usage("Could not read.");
/* EOF */
break;
}
if (write(destf, buffer, n) != n) {
close(sourcef);
close(destf);
exit_with_usage("Could not write.");
}
}
I suppose exit_with_usage calls exit() so does not return
Note in theory write may write less than the expected number of characters without being an error, and the write has to be done in a loop, but in that case it is useless to manage that
read function returns how many bytes were read to buffer(which has buffer_size). Its not always the case actual bytes read has same value as buffer size(consider scenario if there are not enough bytes left in source file to fully fill your buffer). So you should write to destination file not buffer_size(third argument of the write function), but how many bytes have you read - that is readable variable in your code
You should exit when readable returns an error.So
while(readable != 0){
should be
while(readable != -1){
So that loop could be terminataed when an readfile is exhausted.
You see currently after the whole readfile has been read, calling read fails but write is being called repeatedly since execution has no exit path for failure on read. Also write should only write the number of bytes read. So the code would look like this:
char buffer[buffer_size];
int readable=1;
int writeable;
while(readable != -1){
readable = read(sourcef, buffer, buffer_size);
if(readable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not read.");
}
writeable = write(destf, buffer, readable);
if(writeable == -1){
close(sourcef);
close(destf);
exit_with_usage("Could not write.");
}
}
Simple code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 4096
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("Usage %s Src_file Dest_file\n", argv[0]);
exit(1);
}
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t ReadByte = 0;
int src_fd, dst_fd;
// open file in read mode
if ((src_fd = open(argv[1], O_RDONLY)) == -1) {
printf("Failed to open input file %s\n", argv[1]);
exit(1);
}
// open file in write mode and already exists to overwrite
if ((dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 644)) == -1) {
printf("Failed to create output file %s\n", argv[2]);
exit(1);
}
// loop
while (1) {
// read buffer
ReadByte = read(src_fd, buffer, sizeof(buffer));
// error with reading
if (ReadByte == -1) {
printf("Encountered an error\n");
break;
} else if (ReadByte == 0) {
// file end exit loop
printf("File copying successful.\n");
break;
}
// error with writing
if (write(dst_fd, buffer, ReadByte) == -1) {
printf("Failed to copying file\n");
break;
}
}
// Close file
close(src_fd);
close(dst_fd);
exit(0);
}
Run
./program src_file dest_file
I am trying to write a program on how to read a file 10 bytes per time using read, however, I do not know how to go about it. How should I modify this code to read 10bytes per time. Thanks!!!!
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
int main (int argc, char *argv[])
{
printf("I am here1\n");
int fd, readd = 0;
char* buf[1024];
printf("I am here2\n");
fd =open("text.txt", O_RDWR);
if (fd == -1)
{
perror("open failed");
exit(1);
}
else
{
printf("I am here3\n");
if(("text.txt",buf, 1024)<0)
printf("read error\n");
else
{
printf("I am here3\n");
/*******************************
* I suspect this should be the place I make the modification
*******************************/
if(read("text.txt",buf, 1024)<0)
printf("read error\n");
else
{
printf("I am here4\n");
printf("\nN: %c",buf);
if(write(fd,buf,readd) != readd)
printf("write error\n");
}
}
return 0;
}
The final parameter of read() is the maximum size of the data you wish to read so, to try and read ten bytes at a time, you would need:
read (fd, buf, 10)
You'll notice I've also changed the first parameter to the file descriptor rather than the file name string.
Now, you'll probably want that in a loop since you'll want to do something with the data, and you also need to check the return value since it can give you less than what you asked for.
A good example for doing this would be:
int copyTenAtATime (char *infile, char *outfile) {
// Buffer details (size and data).
int sz;
char buff[10];
// Try open input and output.
int ifd = open (infile, O_RDWR);
int ofd = open (outfile, O_WRONLY|O_CREAT);
// Do nothing unless both opened okay.
if ((ifd >= 0) && (ofd >= 0)) {
// Read chunk, stopping on error or end of file.
while ((sz = read (ifd, buff, sizeof (buff))) > 0) {
// Write chunk, flagging error if not all written.
if (write (ofd, buff, sz) != sz) {
sz = -1;
break;
}
}
}
// Finished or errored here, close files that were opened.
if (ifd >= 0) close (ifd);
if (ofd >= 0) close (ofd);
// Return zero if all okay, otherwise error indicator.
return (sz == 0) ? 0 : -1;
}
change the value in read,
read(fd,buf,10);
From man of read
ssize_t read(int fd, void *buf, size_t count);
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.
if(read("text.txt",buf, 1024)<0)// this will give you the error.
First argument must be an file descriptor.
i have this code but every time i try to run it it deletes the source file without giving any output, so how can i fix my problem?
note the question is asking me this:
Write a program that takes two file names from the command line, and copies the reverse of the contents of the first file into the second file, assuming that it is able to open the first file for reading and the second one for writing. If it can’t open the first file for reading, it must neither create nor modify (as the case may be) the second file. This program must use the low-level functions
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3)
{
fprintf(stderr, "usage %s <source> <dest>\n", argv[0]);
exit(-1);
}
at this par i am trying to use the following format: open("outf", O_WRONLY | O_CREAT | O_TRUNC, 0666)
if ((source = open(argv[1],O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
{ //read permission for user on source
fprintf(stderr, "can't open source\n");
exit(-1);
}
if ((dest = creat(argv[2], 0666)) < 0)
{ //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--)
{ //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't read 1 byte\n");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't write 1 byte\n");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
thanks
I am sorry to be rude but did you even read the options you are passing to the first open call? O_CREAT | O_TRUNC?
What do you think those options do? Those options are causing your source file to be deleted.
You need to open your input file with the mode O_RDONLY, i.e. ReaD ONLY not O_WRONLY, i.e. WRite ONLY.
Check this:
int checkstatus(ifstream &in)
{
ios::iostate i;
i = in.rdstate();
if(i & ios::eofbit)
return 0;//cout << "EOF encountered\n";
else if(i & ios::failbit)
return 0;//cout<<"Non-Fatal I/O error\n";
else if(i & ios::badbit)
return 0;//cout<<"Fatal I/O error\n";
return 1;
}
int main()
{
ifstream in;
ofstream o;
in.open("test.txt");
o.open("test1.txt",ios::out);
char c;
in.seekg(0,ios::end);
while(checkstatus(in) != 0)
{
in.seekg(-1,ios::cur);
in.get(c);
in.seekg(-1,ios::cur);
if(checkstatus(in) == 0)
break;
cout<<c;
o.put(c);
}
in.close();
o.close();
return 0;
}
i have made some changes here and it worked very decent but not with very large file!!
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3)
{
fprintf(stderr, "usage %s <source> <dest>\n", argv[0]);
exit(-1);
}
if ((source = open(argv[1], 0666)) < 0)
{ //read permission for user on source
fprintf(stderr, "can't open source\n");
exit(-1);
}
if ((dest = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
{ //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--)
{ //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't read 1 byte\n");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't write 1 byte\n");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
do i need to do something with lseek()?
This question already has answers here:
How do you determine the size of a file in C?
(15 answers)
Closed 3 years ago.
How can I find out the size of a file I opened with an application written in C ?
I would like to know the size, because I want to put the content of the loaded file into a string, which I allocate using malloc(). Just writing malloc(10000*sizeof(char)); is IMHO a bad idea.
You need to seek to the end of the file and then ask for the position:
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
You can then seek back, e.g.:
fseek(fp, 0L, SEEK_SET);
or (if seeking to go to the beginning)
rewind(fp);
Using standard library:
Assuming that your implementation meaningfully supports SEEK_END:
fseek(f, 0, SEEK_END); // seek to end of file
size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
// proceed with allocating memory and reading the file
Linux/POSIX:
You can use stat (if you know the filename), or fstat (if you have the file descriptor).
Here is an example for stat:
#include <sys/stat.h>
struct stat st;
stat(filename, &st);
size = st.st_size;
Win32:
You can use GetFileSize or GetFileSizeEx.
If you have the file descriptor fstat() returns a stat structure which contain the file size.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
// fd = fileno(f); //if you have a stream (e.g. from fopen), not a file descriptor.
struct stat buf;
fstat(fd, &buf);
off_t size = buf.st_size;
I ended up just making a short and sweet fsize function(note, no error checking)
int fsize(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET); //go back to where we were
return sz;
}
It's kind of silly that the standard C library doesn't have such a function, but I can see why it'd be difficult as not every "file" has a size(for instance /dev/null)
How to use lseek/fseek/stat/fstat to get filesize ?
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
void
fseek_filesize(const char *filename)
{
FILE *fp = NULL;
long off;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("failed to fopen %s\n", filename);
exit(EXIT_FAILURE);
}
if (fseek(fp, 0, SEEK_END) == -1)
{
printf("failed to fseek %s\n", filename);
exit(EXIT_FAILURE);
}
off = ftell(fp);
if (off == -1)
{
printf("failed to ftell %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] fseek_filesize - file: %s, size: %ld\n", filename, off);
if (fclose(fp) != 0)
{
printf("failed to fclose %s\n", filename);
exit(EXIT_FAILURE);
}
}
void
fstat_filesize(const char *filename)
{
int fd;
struct stat statbuf;
fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
if (fd == -1)
{
printf("failed to open %s\n", filename);
exit(EXIT_FAILURE);
}
if (fstat(fd, &statbuf) == -1)
{
printf("failed to fstat %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] fstat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);
if (close(fd) == -1)
{
printf("failed to fclose %s\n", filename);
exit(EXIT_FAILURE);
}
}
void
stat_filesize(const char *filename)
{
struct stat statbuf;
if (stat(filename, &statbuf) == -1)
{
printf("failed to stat %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] stat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);
}
void
seek_filesize(const char *filename)
{
int fd;
off_t off;
if (filename == NULL)
{
printf("invalid filename\n");
exit(EXIT_FAILURE);
}
fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
if (fd == -1)
{
printf("failed to open %s\n", filename);
exit(EXIT_FAILURE);
}
off = lseek(fd, 0, SEEK_END);
if (off == -1)
{
printf("failed to lseek %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] seek_filesize - file: %s, size: %lld\n", filename, (long long) off);
if (close(fd) == -1)
{
printf("failed to close %s\n", filename);
exit(EXIT_FAILURE);
}
}
int
main(int argc, const char *argv[])
{
int i;
if (argc < 2)
{
printf("%s <file1> <file2>...\n", argv[0]);
exit(0);
}
for(i = 1; i < argc; i++)
{
seek_filesize(argv[i]);
stat_filesize(argv[i]);
fstat_filesize(argv[i]);
fseek_filesize(argv[i]);
}
return 0;
}
Have you considered not computing the file size and just growing the array if necessary? Here's an example (with error checking ommitted):
#define CHUNK 1024
/* Read the contents of a file into a buffer. Return the size of the file
* and set buf to point to a buffer allocated with malloc that contains
* the file contents.
*/
int read_file(FILE *fp, char **buf)
{
int n, np;
char *b, *b2;
n = CHUNK;
np = n;
b = malloc(sizeof(char)*n);
while ((r = fread(b, sizeof(char), CHUNK, fp)) > 0) {
n += r;
if (np - n < CHUNK) {
np *= 2; // buffer is too small, the next read could overflow!
b2 = malloc(np*sizeof(char));
memcpy(b2, b, n * sizeof(char));
free(b);
b = b2;
}
}
*buf = b;
return n;
}
This has the advantage of working even for streams in which it is impossible to get the file size (like stdin).
If you're on Linux, seriously consider just using the g_file_get_contents function from glib. It handles all the code for loading a file, allocating memory, and handling errors.
#include <stdio.h>
#define MAXNUMBER 1024
int main()
{
int i;
char a[MAXNUMBER];
FILE *fp = popen("du -b /bin/bash", "r");
while((a[i++] = getc(fp))!= 9)
;
a[i] ='\0';
printf(" a is %s\n", a);
pclose(fp);
return 0;
}
HTH