0

I would like to know if there is a method for reading characters from a file and saving them into an array without a specified array length.

In normal situation I read all the characters and count them. (step 1) Then I create the array with malloc and read the characters from the file, so I am forced to read the whole file twice. Can it be done with only one reading?

MaXiMkA
  • 449
  • 3
  • 6
  • 14

3 Answers3

2

The normal way to do this is to do a fseek to end of file, then you are not actually reading all the characters twice.

fseek( fp, 0L, SEEK_END );
size_t size = ftell(fp);
fseek( fp, 0L, SEEK_SET );
char* buffer = malloc( size );
fread( buffer, 1, size, fp );
AndersK
  • 35,813
  • 6
  • 60
  • 86
  • line 4 gives me: [Error] invalid conversion from 'void*' to 'char*' [-fpermissive] – MaXiMkA Jan 10 '14 at 13:03
  • the compiler is then compiling it as C++ - then a cast is necessary. – AndersK Jan 10 '14 at 13:44
  • so OP should compile it as `C` (as he tagged this question `C`) – zoska Jan 10 '14 at 13:45
  • yes that is better of course! :) – AndersK Jan 10 '14 at 13:48
  • _Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state._ Please note that there is no guarantee that require the size of the file in this way.、 – BLUEPIXY Jan 10 '14 at 15:57
  • could you bother to mention where your quote comes from because AFAIK I have never encountered an issue as you describe it – AndersK Jan 10 '14 at 19:18
1

You can find the number of characters in the file by finding the size of the file.

int size = 0;
char* aFileContents = NULL;

fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);  // reset the file pointer

aFileContents = (char*)malloc(size);

//  use the data

free(aFileContents);
PermanentGuest
  • 5,213
  • 2
  • 27
  • 36
  • I havent been working with C for ages but does fseek return the position of the actual character or the actual byte? – Daniel W. Jan 10 '14 at 12:40
  • 2
    @DanFromGermany it depends on how the file was opened: if in normal/text mode [`ftell` returns an unspecified value](http://en.cppreference.com/w/c/io/ftell) that is only meaningful to `fseek`. If it is opened in binary mode then `ftell` returns the position in bytes. – Kninnug Jan 10 '14 at 12:42
  • 1
    only true with fixed-witdh encoding. you can't use this for unicode or other variable width encodings – phuclv Jan 10 '14 at 13:14
0

The above solutions are quite right. But I want to add that we should open the file "rb" that is binary mode to make them work. If you open the file with simple "r"/"a", then the file will get opened in text mode. fseek and ftell method gives us byte length of the entire file. If you are working with binary data (do not use fscanf/fprintf) , i.e. using fread and fwrite, then it suits you best. I am not sure if that will work if you use fscanf/fprintf/fgets For example

#include<stdio.h>
int main() {
  FILE *fid;
  char *data;
  long int size;
  fid = fopen("filename", "rb");
  fseek(fid, 0l, SEEK_END);
  size = ftell(fid);
  data = (char *) malloc(size);
  fseek(fid, 0l, 0);

  data = fread(data, 1, size, fid);
  // Use the data !!
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Chinmay
  • 1
  • 2