Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I would like to merge two files using open and file descriptor. Moreover I would like to separate the content of the first file with - before writing the the content of the second file.
I did the following :
void merge (char* fileName, char *fileName1) {
int fd = open(fileName, O_RDWR);
char c;
while (read(fd, c, 1) > 0) {//going at the end of the first file
}
char next[] = "\n";
char charc[] = "-";
write (fd, next, strlen(next));
for (int i = 0; i < 80; i++) {
if (write (fd, charc, strlen(charc)) == -1) {
perror("error : ");
}
}
write (fd, next, strlen(next));
int fd1 = open(fileName1, O_RDWR);
while(read(fd1, &c, 1) > 0) {
write(fd, &c, sizeof(c));
}
close(fd1);
close(fd);
}
Is there a better way to write this code ? Moreover I have a little problem even if it works it seems like I don't have the right to read the new file. For example if I do cat newFile I have a permission denied.
Is there a better way to write this code ?
You are not handling errors of all calls. All of syscalls open, write, read and close return -1 on error and set errno and may do that at any time. EINTR could be handled.
going at the end of the first file open has O_APPEND flag mode that is used for appending data.
Copying one character at a time is very not optimal. With glibc standard library you could use BUFSIZ bytes at a time that is chosen for fast I/O output. You could make a copy of a big chunk size at a time that is a power of 2, like 2048 or 4096.
There is little reason to use file descriptors here - prefer to use standard FILE * handling, which would make your code portable and also buffer the data for faster I/O.
If you wish to create the file use O_CREAT and add the third argument to open that is the mask of permissions of new file.
On linux there is splice(2) system call that can be used to append data on kernel side for maximum efficiency.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have to write a program in C in which I have to read some values from stdin and also to do it with the quickest function in C. The stdin is preloaded in a form like this:
int,int\n
char\n
int,int,int\n ex...
I'm asking for help because scanf is too slow for the time requirement of the project and also because I have some difficulties to read because of the ',' that I don't really need and that causes me problems.
I've tried with gets or getchar, but I didn't manage to make it work.
The fastest way to read stdin ("standard in" - 0 file descriptor) is to use read function from <unistd.h.>:
char buff[1024] = {0}; /* zero-initialize */
ssize_t res = read(0, &buff, sizeof(buff));
/* res is amount of bytes read; -1 if error */
Here is an example of program which reads 1024 bytes of stdin and echoes it to stdout (file descriptor: 1) (no error handling for simplicity):
#include <unistd.h>
#define BUFSIZ 1024
int main() {
char buff[BUFSIZ] = {0}; /* zero-initialize */
ssize_t nread = read(0, buff, BUFSIZ);
/* pass amount of bytes read as a byte amount to write */
write(1, buff, nread);
return 0;
}
This is the fastest way to read from stdin because read is native libc wrapper for a kernel syscall. By the way, you can use -O3, or even -Ofast compiler options to make it optimize the code.
Also, keep in mind that read and write are not guaranteed to read/write exactly as many bytes as you want, you should call it in a loop like this:
size_t to_write = sizeof(buff); /* example, can be result of read() */
int fd = 1;
size_t nwrote = 0;
while ((nwrote += write(1, buff, to_write) < to_write) {
/* pointer arithmetic to create offset from buff start */
write(fd, buff+nwrote, to_write - nwrote);
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to read from a fifo and i am not understanding it's behaviour.
This is the write side, write.c:
for(int i = 1;i<argc;i++){
if(write(fifoFd,argv[i],strlen(argv[i])) <= 0)
perror("Error writing");
}
And this is the read side, read.c:
char buf[1024];
while(1){
int b = read(fifoFd,buf,1024);
if(b<=0) break;
}
printf("%s\n",buf);
First i start read.c ./read then i execute ./write
If i execute write like this ./write backup *.txt sometimes i get what i expected, i.e, backupexample1.txtexample2.txt.
But sometimes i only get example1.txtexample2.txt and i am not understanding this, where is "backup"?
Your code:
while(1){
int b = read(fifoFd,buf,1024);
if(b<=0) break;
}
printf("%s\n",buf);
You loop, each time through the loop you overwrite the buffer, and then you print the buffer. So, sometimes, you read "backup" followed by "example1.txtexample2.txt" (which overwrites "backup"), other times you read the whole lot at once in a single read.
If you change the loop to read into the unpopulated portion of the buffer, it will behave consistently:
int read = 0;
while(read != 1024){
int b = read(fifoFd,buf+read,1024-read);
if(b<=0) break;
read += b;
}
printf("%s\n",buf);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
What is the difference between running an already compiled C program with a.out file_name_here and a.out < file_name_here?
I remember something about Linux pipelines, but I cannot remember how to make the a.out file accept a file using the < symbol.
Basically what I am asking is this: how does the C code look for a C program that:
file_name_here is a text file with "hello world" as content
terminal gets "a.out < file_name_here" in command line
terminal shows output: "hello world"
a.out file_name_here passes "file_name_here" as an argument.
a.out < file_name_here is processed by the shell and presents the contents of "file_name_here" to the program on its "stdin".
Note that when you type a.out < filename, the shell handles the I/O redirection. The program is run with its standard input coming from the named file instead of from the terminal. When you type a.out filename, the program must deal with opening the file, reading it (and preferably closing it too). Neither of these examples uses a pipe. You could write cat file1 file2 file3 | a.out which would use a pipe and supply the contents of the three files as the standard input to the program.
Many programs on Unix systems are filters. If they are given file names to process, those are read. If they are given no file names, then they read standard input instead. An example of such a program is grep; other examples include cat and sort.
The general solution, in outline, is:
extern void process_file(FILE *fp); // Where the real work is done
int main(int argc, char **argv)
{
int rc = EXIT_SUCCESS;
if (argc == 1)
process_file(stdin);
else
{
for (int i = 1; i < argc; i++)
{
FILE *fp = fopen(argv[i], "r");
if (fp == 0)
{
fprintf(stderr, "%s: failed to open file %s for reading\n",
argv[0], argv[i]);
rc = EXIT_FAILURE;
}
else
{
process_file(fp);
fclose(fp);
}
}
}
return rc;
}
This will process any command line arguments as files to be read, resorting to reading standard input if no files are specified on the command line. There are legions of extra tweaks you can make to this outline. You can easily add option processing with getopt() (or getopt_long() if you're using GNU), and you can treat a file name of - as standard input if you wish. You can exit on failure to open a file if you think that's appropriate (sometimes it is; sometimes it isn't — grep doesn't, for example). You can pass the file name to the process_file() function. You can have the process_file() function report success failure, and track whether everything worked, exiting with zero only if all the operations were successful.
Just realized the problem I had. The < symbol means that the shell replaces normal user input in C with the content of the file, so all the normal calls such as fgets and sscanf work on it.
I'm working on a client/server program where the client sends/receives files. The files may be text files or binary files. However, I am not sure what changes I need to make, if any, to accommodate for either file type. Basically I am looking to read/write to a file on the server side without caring what type of file it is, I would like to be able to do so without checking what type of file it was. Would code like this work? Why or why not?
Server snippet:
//CREATING/WRITING TO A FILE
//we are ready to begin reading data from the client, and storing it
int fd = open(pathname, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
while(nbytes < bytes)
{
//only read the neccessary # of bytes: the remaining bytes vs max buffer size
int min_buffer = (bytes - nbytes) < BUFFER_SIZE ? (bytes - nbytes) : BUFFER_SIZE;
length = recv( client->client_socket, contents, min_buffer, 0);
if(fd < 0) //the fd is bad, but we need to continue reading bytes anyway
{
nbytes += length;
continue;
}
if(length <= 0)
break;//string empty or error occurred...this error means the client closed?
if(write(fd, contents, min_buffer) != min_buffer)
{
//printf("There was an error writing to the file.\n");
}
else
{
nbytes += length;
}
}
//READING A STORED FILE AND SENDING THE DATA TO CLIENT
int fd = open(pathname, O_RDWR, S_IRUSR | S_IWUSR);
if(fd >= 0)
{
while(bytes > 0)
{
bytes = read(fd, buffer, BUFFER_SIZE );
if(bytes > 0)//we have read some bytes
{
//send the client the data
write(client->client_socket, buffer, bytes);
}
else if(bytes < 0)
{
//some error occured
write( client->client_socket, "ERROR: Could not read\n", 22);
return;
}
}
}
So if the client sends a binary file vs a text file, would this code cause issues? (We can assume the client knows what type of file to expect.)
Note: Another confusing detail about this is that there are tutorials for writing/reading binary files in c that didn't seem to have any real differences over regular files, which is what lead me here.
Just do everything with "binary" files. Linux has no difference between "text" and "binary" in a file on OS level, there are just files with bytes in it. Ie. expect that a file contains every possible byte value, and don´t write different code for different kinds of content.
There is a difference in Windows: Text mode in Windows means that a line break (\n) in the program gets converted to/from \r\n when writing to / reading from a file. The written text file read in binary mode will contain this two bytes instead of the original \n and vice-versa. (Additionally, MS isn´t very clear in the documentation that this is the only difference, it can confuse beginners easily.)
If you use standard C fopen and fclose instead of Linux-specific open etc., you can specify to open a file in binary or text mode (on Linux too). This is because code with fopen should work on Windows and Linux without any OS-specific changes; but what you choose in fopen doesn´t matter when running on Linux (which can be verified by reading the source code of fopen etc.)
And about the sockets:
Linux: No difference (again)
Windows: No difference too. There are just bytes, and no strange line break conversions.
I tore my hair out for a day over a binary/text file issue. I was outputting binary data into "files" (apparently text files ... after years and years of C I'd always thought a file was a file) and kept getting spurious characters inserted into the output. I went so far as to download a new compiler but had the same problem. The issue? When I output hex A using any of the family of fprint statements, hex D was being inserted. Yes, line feed characters -- A -- were being replaced by carriage return/line feed -- DA. It's a legacy "end of line" issue based on how different systems have developed. The tough part of finding the problem was realizing A was being interpreted as more than just a binary field, but actually being recognized as a line feed.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm taking an Operating Systems class for university and we have an assignment as follows:
Write a program that can be used to create a child process.
The child process should create a file called “Listx.txt” and ask the user for data to write to it. The parent process should read the data from the file and display it on the screen.
Modify the program to make the parent read the file and display the contents five times. It should pause for 1 second between each display.
Modify the program to make the parent read the file and display the contents over and over again until the user sends SIGSTOP. It should pause for 1 second between each display.
And this is the code I've come up with:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
int x;
int y = 0;
pid_t pid = fork();
if (pid==0)
{
printf("Hi, i am the child\n");
int fd;
fd = open("listx.txt", O_RDWR |O_CREAT |O_TRUNC);
printf ("enter Number");
scanf("%d\n",x);
char wd [100];
ssize_t nr;
wd[0]=x;
nr = write (fd, wd, sizeof (wd));
}
else
printf(" I am the parent, the child is %d\n",pid);
{
int fd;
fd = open ("listx.txt", O_RDONLY);
if (fd == -1)
{
printf("file not opened \n");
}
else
{
printf("file found \n");
}
char wd[100];
ssize_t nr;
nr = read (fd, wd, sizeof (wd));
if (nr == -1)
{
printf("file not read \n");
}
else
{
while (y < 5){
printf("The file has %s \n",wd);
sleep(1);
}
}
return 0;
The program compiles (through GCC) but I think I have the logic wrong.
May you kindly assist with helping me solve this?
This:
scanf("%d\n",x);
char wd [100];
ssize_t nr;
wd[0]=x;
is rather wrong, in more ways than one:
You must pas &x to scanf(), since it can't store the value unless given an address. Instead you pass the current value of x, causing undefined behavior.
You assign the value of x into a single character, which is going to drop lots of bits. This is probably not what you want to do.
You use file descriptors even after detecting that they are not valid.
Please figure out how to maximize the diagnostics (warnings and errors) from your compiler, and observe what it says. Many of these problems will generate warnings. For GCC, this manual page is informative. Basically, start out by adding -Wall -Wpedantic -Wextra to your compiler invocation.
exit the child (_exit(0))
wait in the parent until child has finished (waitpid(2) et.al.)
Apart from scanf problems I see printf(" I am the parent, the child is %d\n",pid); that I suspect that you wanted inside the curly brackets.
Moreover you need to ensure that the child wrote before starting reading so the first instruction in the parent should be waitpid(pid,&status,0); that waits for the child termination (and indirectly for the file being written). Note that the fact that the code of the child is on top doesn't mean that it will executed as first (I think this is what the exercise wants to highlight).
Another thing that you should always do as a good programmer is closing your file after writing.