#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#pragma warning(disable:4996)
size_t file_size(FILE *fd){
if (fd == NULL) {
printf("File not found");
return -1;
}
fseek(fd, 0, SEEK_END);
return ftell(fd);
}
int main() {
FILE *in;
FILE *out;
char buffer[2] = { 0 };
int n = 0;
in = fopen("test.txt", "rb");
if (in == NULL) {
printf("cona\n"); return -1;
}
out = fopen("out.txt", "wb");
if (out == NULL) {
printf("cona1\n"); return -1;
}
size_t size = file_size(in);
for(n = 0; n < size; n += 2){
if (fread(&buffer, sizeof(char), 2, in) !=2) {
printf("cona2 \n");
} //keeps given erros in here
fwrite(&buffer, sizeof(char), 2, out);
memset(buffer, 0, sizeof(buffer));
}
printf(" \n in: %zu \n", size);
printf(" \n out: %zu \n", file_size(out));
fclose(out);
fclose(in);
system("PAUSE");
return(0);
}
My main question in here is if fread fuction works in a cycle, and if i can ask just n numbers of element in the file ervytime, and not the all file at once, i try this but it keeps me given error reading the file, it doesn't read anything.
There is a problem after your function finds the file size with
fseek(fd, 0, SEEK_END);
return ftell(fd);
because you do not rewind to the start of the file before trying to read from it.
rewind(fd);
or
fseek(fd, 0, SEEK_SET);
Related
I've been making the program from CS50'x about reversing the .WAV files. Seems to work fine, however the cs50's check finds an error. Don't know where it is, the code seems to be alright and there I can't find any problem.
I tried to change 'i' - iterator in for-loop but when set as = infile_size - block_size the file won't be converted / reversed.
My code below:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "wav.h"
int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);
int main(int argc, char *argv[])
{
// Ensure proper usage
// TODO #1
// check if command-line arguments = argv[0], argv[1], argv[2] = 3 in sum
if (argc != 3)
{
if (argc < 3)
{
printf("not enough command-line args\n");
}
else
{
printf("too much command-line args\n");
}
return 1;
}
// remember filenames
char *infile = argv[1];
char *outfile = argv[2];
// open input file for reading
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("could not open the infile\n");
return 1;
}
// read header into an array
WAVHEADER header;
fread(&header, sizeof(header), 1, inptr);
// use check_format to ensure WAV format
check_format(header);
// open output file for writing
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
printf("couldn't open the outfile\n");
fclose(inptr);
return 1;
}
// write header to file
fwrite(&header, sizeof(header), 1, outptr);
// use get_block_size to calculate size of block
int block_size = get_block_size(header);
printf("block_size: %i\n", block_size);
if (block_size < 0)
{
printf("block_size with no size\n");
return 1;
}
// write reversed audio to file
// 1. declare an array to store each block of audio
char *buffer = malloc(block_size * sizeof(char));
if (buffer == NULL)
{
printf("no memory location");
return 1;
}
// get the size of the input file
fseek(inptr, 0, SEEK_END);
long int infile_size = ftell(inptr);
printf("file_size: %li\n", infile_size);
// iterate through the input file audio data
for (long int i = infile_size; i >= 0; i -= block_size)
{
// move the file indicator to the start
fseek(inptr, i, SEEK_SET);
// read from inptr each size
fread(buffer, sizeof(char), block_size, inptr);
// write in outfile
fwrite(buffer, sizeof(char), block_size, outptr);
}
// free
free(buffer);
// close files:
fclose(inptr);
fclose(outptr);
}
int check_format(WAVHEADER header)
{
// TODO #4
if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E')
{
printf("This is the type .wav\n");
return 0;
}
else
{
printf("File is not the type .wav\n");
return 1;
}
}
int get_block_size(WAVHEADER header)
{
// TODO #7
// check if channels are mono or audio
if (header.numChannels == 1 || header.numChannels == 2)
{
int block_size;
block_size = header.numChannels * (header.bitsPerSample / 8);
return block_size;
}
else
{
printf("Not supported\n");
return 1;
}
}
Thanks in advance!
This is my program code that can load inputs 1GB, 2GB, but I would need to load files larger than 2GB. I work at Windows.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *stream;
size_t size;
int fileSize = 0;
char *input;
// Open file, find the size of it
stream = fopen("3GB.bin", "rb");
fseek(stream, 0L, SEEK_END);
fileSize = ftell(stream);
fseek(stream, 0L, SEEK_SET);
input = (char *)malloc(fileSize + 1);
// Stream file into memory
size = fread(input, 1, fileSize, stream);
input[size] = 0;
fclose(stream);
printf("size file is: %d\n", fileSize);
free(input);
return 0;
}
The problem is that it does not load files larger than 2GB at all...
Don't know where the problem is?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main()
{
FILE *stream;
size_t size;
uint32_t fileSize = 0;
char *input;
int result1, result2;
// Open file, find the size of it
stream = fopen("4GB.bin", "rb");
if (result1 = _fseeki64(stream, 0L, SEEK_END) != 0)
{
printf("_fseeki64 result1 error\n");
}
fileSize = _ftelli64(stream);
if (result2 = _fseeki64(stream, 0L, SEEK_SET)!= 0)
{
printf("_fseeki64 result2 error\n");
}
input = (char *) malloc(fileSize + 1);
if (input == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
//Stream file into memory
size = fread(input, 1, fileSize, stream);
input[size] = 0;
fclose(stream);
printf("size file is: %u\n", fileSize);
free(input);
return 0;
}
Is it possible to stop scanning from file in the middle of the file?
For example if I want to change this code to for loop with size/2.
edit: Can you please help me understand why i != toScan size(secondSize)?
fseek(toScan, 0, SEEK_END);
secondSize = ftell(toScan);
rewind(toScan);
fseek(toScan, 0.5 * secondSize, SEEK_SET);
while (fgetc(toScan) != EOF){
rewind(signature);
fseek(toScan, -1, SEEK_CUR);
if (fgetc(toScan) == fgetc(signature)){
fseek(toScan, -1, SEEK_CUR);
temp = ftell(toScan);
elements = fread(secondBuffer, 1, size, toScan);
fseek(toScan, temp + 1, SEEK_SET);
if (strcmp(secondBuffer, buffer) == 0){
toReturn = 3;
break;
}
}
rewind(signature);
strncpy(secondBuffer, "", sizeof(secondBuffer));
i++;
}
Yes, you can get the file size and then, in a loop:
for (i = 0; i < file_size / 2; i++) {
int c = fgetc(file);
...
}
An example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *file;
long size, i;
int c;
file = fopen("demo.c", "rb");
if (file == NULL) {
perror("fopen");
exit(EXIT_FAILURE);
}
if (fseek(file, 0, SEEK_END) == -1) {
perror("fseek");
exit(EXIT_FAILURE);
}
size = ftell(file);
if (size == -1) {
perror("ftell");
exit(EXIT_FAILURE);
}
if (fseek(file, 0, SEEK_SET) == -1) {
perror("fseek");
exit(EXIT_FAILURE);
}
for (i = 0; i < size / 2; i++) {
c = fgetc(file);
putchar(c);
}
fclose(file);
return 0;
}
I wrote a very simple file corruptor for fun, but to my surprise, the "corrupted" file ends up being smaller in size than the original.
Here is the corruption function that is supposed to replace bytes but not to delete them:
void
corruptor(char *inputname, int percent)
{
FILE *input;
FILE *output;
int filesize;
char *outputname = append_name(inputname);
// Duplicate file
cp(outputname, inputname);
// Open input and output
input = fopen(inputname, "r");
if (input == NULL)
{
printf("Can't open input, errno = %d\n", errno);
exit(0);
}
output = fopen(outputname, "w+");
if (output == NULL)
{
printf("Can't open output, errno = %d\n", errno);
exit(0);
}
// Get the input file size
fseek(input, 0, SEEK_END);
filesize = ftell(input);
// Percentage
int percentage = (filesize * percent) / 100;
srand(time(NULL));
for (int i = 0; i < percentage; ++i)
{
unsigned int r = rand() % filesize;
fseek(output, r, SEEK_SET);
unsigned char corrbyte = rand() % 255;
fwrite(&corrbyte, 1, sizeof(char), output);
printf("Corrupted byte %d\n", r);
}
fclose(input);
fclose(output);
}
output = fopen(outputname, "w+");
This deletes the contents of the file, To open the file for reading and writing without deleting the contents, use mode "r+".
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