SdFat icon indicating copy to clipboard operation
SdFat copied to clipboard

int FatFile::read(void*, size_t)' is inaccessible within this context

Open Twilight-Logic opened this issue 4 years ago • 4 comments

When I try to use the read() method on an ifstream or fstream object I get this compile error:

'int FatFile::read(void*, size_t)' is inaccessible within this context

Using getline() returns whole lines and works as expected.

Using get() in a loop like so:

  while (sdinout.get(c)) {
    Serial.print(c);
  }

results in most characters being missed and spurious fragmented output being sent to the serial. It would appear that get() does not work very well either.

Checking the documentation is would appear that read() is listed as a private function which explains the above error, but why is it private? I am looking to read the file as binary byte by byte. Neither getline() nor get() appear suitable to the task as they both stop on and strip delimiters. I need to capture all bytes including those that might be considered to be delimiters.

One possible option might be to use SdFile myfile and file.fgets(). Some sources suggest this is slow in comparison although I haven't done any tests yet.

So, are the stream methods .get() and .read() not meant to be used in the context of the SdFat library?

Twilight-Logic avatar Jul 13 '21 11:07 Twilight-Logic

istream& get(char& ch) always return *this. get(char& ch) reads one character and stores it in ch if available otherwise, leaves ch unmodified and sets failbit. The standard says get(char&) should also set the eofbit.

Looks like read() had a problem and I never fixed it. Almost no one uses iostreams so you are the first to catch the missing read.

I will put read() and readsome() on the to do list. May be a long time until I get to it. My memory is read had a problem since it must return *this and conflicts with use of the underlying read.

The implementation of iostreams is slower than File and I only kept it for some comparability with SdFat V1.

Edit: Looks like iostreams has conflicts with other Arduino types so I will probably drop all support for these functions.

greiman avatar Jul 13 '21 12:07 greiman

This test of get() seems to work.

void testGet() {
    ifstream fin("get.txt");
    while (true) {
      int i = fin.get();
      if (i < 0) break;
      cout << char(i);
    } 
}

With get(c) you will need to check the failbit for EOF.

greiman avatar Jul 13 '21 13:07 greiman

Thanks for having a look and confirming the problem with read() in fstreams. I would have used SdFile but for the fact that numerous examples seem to use ofstream/ifstream/fstream. I suspect that this may be down to overlap/confusion with C/C++ which is not the same as writing for the Arduino. I have now converted my code to use the SdFile object and all the methods work when using that. If there still ends up being a need to use the << or >> operators, then I can always use ArduinoInStream or ArduinoOutStream, but I don't think it is strictly neccessary.

For whatever reason got back only a block character for each iteration when using get(). I think I may have been using fin.get(c) rather than c = fin.get() but I don't have the code anymore to confirm. Thanks for the note on the failbit.

I realised I didn't give version numbers, but for reference:

Arduino IDE: 1.8.15 SdFat library: 2.0.7 Linux Mint 19.3, 64-bit

Compiled binary running on an ATMega1284P MCU.

Twilight-Logic avatar Jul 14 '21 10:07 Twilight-Logic

You must use an int type to make get() work. You must test for failbit to make get(c) work.

I need to do a major change to make read work since size_t read(void*, size_t) is in the parent of ifstream and fstream.

read() becomes ambiguous and fails in may apps that work with a correct iostreams implementation. I will need to make the the File object be internal to the fstream types.

greiman avatar Jul 14 '21 12:07 greiman