I'm not good at C and I'm trying to do something simple. I want to open a binary file, read blocks of 1024 bytes of data and dump into a buffer, process the buffer, read another 1024 byes of data and keep doing this until EOF. I know how / what I want to do with the buffer, but it's the loop part and file I/O I keep getting stuck on.
PSEUDO code:
FILE *file;
unsigned char * buffer[1024];
fopen(myfile, "rb");
while (!EOF)
{
fread(buffer, 1024);
//do my processing with buffer;
//read next 1024 bytes in file, etc.... until end
}
fread() returns the number of bytes read. You can loop until that's 0.
FILE *file = NULL;
unsigned char buffer[1024]; // array of bytes, not pointers-to-bytes
size_t bytesRead = 0;
file = fopen(myfile, "rb");
if (file != NULL)
{
// read up to sizeof(buffer) bytes
while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0)
{
// process bytesRead worth of data in buffer
}
}
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
int fd = open("example.txt", O_RDONLY);
while ((byte = read(fd, buffer, sizeof(buffer))) != 0) {
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
close(fd);
return 0;
}
Edited code added
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
// open file in read mode
int fd = open("example.txt", O_RDONLY);
// file opening failure
if (fd == -1) {
printf("Failed to open file\n");
return -1;
}
// loop
while (1) {
// read buffer
byte = read(fd, buffer, sizeof(buffer));
// error
if (byte == -1) {
printf("Encountered an error\n");
break;
} else if (byte == 0) {
// file end exit loop
printf("File reading end\n");
break;
}
// printf file data
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
// Close file
close(fd);
return 0;
}
Related
I'm attempting to read 4 bytes from the start of a character buffer, but I'm having an issue. memcpy is returning junk.
buffer contains the contents of the file. Using breakpoints I see that the file starts with 41 53 45 46 or ASEF in ASCII. This is the file signature for an Adobe Swatch File.
But when I copy those 4 bytes from a character buffer, to a 4 byte array signature, I get random data.
Any idea what I'm doing wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main(int argc, char **argv)
{
errno_t err = NULL;
FILE *fptr = NULL;
long fileSize = 0;
unsigned char* buffer;
int i, bytesRead;
char signature[4] = { 0 };
err = fopen_s(&fptr, argv[1], "rb");
if (err || fptr == NULL) {
fprintf(stderr, "Could not open file: %s\n", argv[1]);
return 1;
}
// Get filesize
fseek(fptr, 0, SEEK_END);
fileSize = ftell(fptr);
rewind(fptr);
// Allocate memory to store file contents
buffer = malloc(fileSize);
if (buffer == NULL) {
fprintf(stderr, "Could not allocate %i bytes of memory\n", fileSize);
return 1;
}
// Read file contents into buffer
bytesRead = fread(buffer, 1, fileSize, fptr);
if (bytesRead == 0) {
fprintf(stderr, "Failed to read bytes from file: %s\n", argv[1]);
return 1;
}
// Read and check signature
memcpy(signature, &buffer, 4);
fclose(fptr);
return 0;
}
This line is wrong:
memcpy(signature, &buffer, 4);
You want to copy the data in your buffer, not the value of the buffer pointer itself. That means you want:
memcpy(signature, buffer, 4);
I want to make copy/paste with using c FILE but i need to add read/write buffer too and I am not sure how to add it. Is there any function similar to regular read/write..Code is below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) {
FILE* fsource, * fdestination;
printf("enter the name of source file:\n");
char sourceName[20], destinationName[20];
strcpy(sourceName, argv[1]);
strcpy(destinationName, argv[2]);
fsource = fopen(sourceName, "r");
if (fsource == NULL)
printf("read file did not open\n");
else
printf("read file opened sucessfully!\n");
fdestination = fopen(destinationName, "w");
if (fdestination == NULL)
printf("write file did not open\n");
else
printf("write file opened sucessfully!\n");
char pen = fgets(fsource);
while (pen != EOF)
{
fputc(pen, fdestination);
pen = fgets(fsource);
}
fclose(fsource);
fclose(fdestination);
return 0;
}
Here's a reworking of your code (sans some error handling) that reads and writes in 256-byte increments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *sourceName = argv[0];
char destName[256];
snprintf(destName, 256, "%s.copy", sourceName);
printf("Copying %s -> %s\n", sourceName, destName);
FILE *fsource = fopen(sourceName, "rb");
FILE *fdest = fopen(destName, "w");
char buffer[256];
for (;;) {
size_t bytesRead = fread(buffer, 1, 256, fsource);
if (bytesRead == 0) {
break;
}
if (fwrite(buffer, 1, bytesRead, fdest) != bytesRead) {
printf("Failed to write all bytes!");
break;
}
printf("Wrote %ld bytes, position now %ld\n", bytesRead, ftell(fdest));
}
fclose(fsource);
fclose(fdest);
return 0;
}
The output is e.g.
$ ./so64481514
Copying ./so64481514 -> ./so64481514.copy
Wrote 256 bytes, position now 256
Wrote 256 bytes, position now 512
Wrote 256 bytes, position now 768
Wrote 256 bytes, position now 1024
[...]
Wrote 168 bytes, position now 12968
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 a problem at my C-lecture skill practice. My exercise is to read a text document (which is in the same directory like the program) char by char and write it reversed (so from the end to the beginning, char by char) at the Terminal (i have to work at Ubuntu).
Unfortunately it doesn't work - "read" only reads newline-chars (\n).
Can you find my mistake?
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int two_char_back = (-1)*sizeof(char); //shift-value for char
int one_back = -1; //shift-value for "no shift"
int length = lseek(fd, one_back, SEEK_END);//setting to one before oef
int i = 0; //for the loop
char buffer;
char* pbuffer = &buffer; //buffer for writing
while (i < length){
if (read(fd, pbuffer, sizeof(buffer)) == -1){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, pbuffer, sizeof(buffer)) == -1){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
lseek(fd, two_char_back, SEEK_CUR); //STEPPING
i++;
}
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This is wrong:
int two_char_back = (-1)*sizeof(char);
sizeof(char) is 1, you need -2
Haven't tried running it, but looks like two_char_back should be -2. The read advances the cursor, so -1 keeps reading the same one.
Also, just an option, you could make it more efficient by reading the whole file in then reversing it, then writing.
You have a typo in following line:
int two_char_back = (-1)*sizeof(char);
It must be:
int two_char_back = (-2)*sizeof(char);
As read() increments a cursor, you are actually reading the same character all the time e.g:
example text
^
|
After reading:
example text
^
|
After seeking:
example text
^
|
Thanks for your advices a lot!
& Thanks to my colleagues!
Now it works but I created kind of a new version, here it is:
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY); //OPENING
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int file_size = lseek(fd, 0, SEEK_END); //setting to eof
int i = file_size-1; //for the loop, runs from the end to the start
char buffer;
//the files runs from the end to the back
do{
i--;
lseek(fd, i, SEEK_SET); //STEPPING from the start
if (read(fd, &buffer, sizeof(buffer)) != sizeof(buffer)){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, &buffer, sizeof(buffer)) != sizeof(buffer)){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
}while (i != 0);
buffer = '\n';
write(STDOUT_FILENO, &buffer, sizeof(buffer));//no error-det. due to fixed value
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I read an exec'd program's stdout using a pipe:
int pipes[2];
pipe(pipes);
if (fork() == 0) {
dup2(pipes[1], 1);
close(pipes[1]);
execlp("some_prog", "");
} else {
char* buf = auto_read(pipes[0]);
}
To read from stdout, I have a function auto_read which automatically allocates more memory as needed.
char* auto_read(int fp) {
int bytes = 1000;
char* buf = (char*)malloc(bytes+1);
int bytes_read = read(fp, buf, bytes);
int total_reads = 1;
while (bytes_read != 0) {
realloc(buf, total_reads * bytes + 1);
bytes_read = read(fp, buf + total_reads * bytes, bytes);
total_reads++;
}
buf[(total_reads - 1) * bytes + bytes_read] = 0;
return buf;
}
The reason I do it this way is I don't know how much text the program is going to spew out ahead of time, and I don't want to create an overly large buffer and be a memory hog. I'm wondering if there is:
A cleaner way to write this.
A more memory or speed-efficient way of doing this.
Use popen if you only need to read from a process and are on a *NIX platform:
FILE *programStdout = popen("command", "r");
// read from programStdout (fread(), fgets(), etc.)
char buffer[1024];
while (fgets(buffer, 1024, programStdout))
{
puts(buffer);
}
EDIT: You asked for a way to map a programs output to a file, so here you go:
#import <stdio.h>
#import <unistd.h>
#import <sys/mman.h>
void *dataWithContentsOfMappedProgram(const char *command, size_t *len)
{
// read the data
char template[] = "/tmp/tmpfile_XXXXXX";
int fd = mkstemp(template);
FILE *output = fdopen(fd, "w+");
FILE *input = popen(command, "r");
#define BUF_SIZ 1024
char buffer[BUF_SIZ];
size_t readSize = 0;
while ((readSize = fread(buffer, 1, BUF_SIZ, input)))
{
fwrite(buffer, 1, readSize, output);
}
fclose(input);
input = NULL;
#undef BUF_SIZ
// now we map the file
long fileLength = ftell(output);
fseek(output, 0, SEEK_SET);
void *data = mmap(NULL, fileLength, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, 0);
close(fd);
if (data == MAP_FAILED)
return NULL;
return data;
}
int main()
{
size_t fileLen = 0;
char *mapped = dataWithContentsOfMappedProgram("echo Hello World!", &fileLen);
puts(mapped);
munmap(mapped, fileLen);
}