bitbank2 / unzipLIB

An embedded-friendly library for decompressing files from zip archives
Apache License 2.0
52 stars 11 forks source link

Chunk by chunk read #4

Closed samsmith94 closed 2 years ago

samsmith94 commented 2 years ago

Hi,

I'm still not able to read the unzipped data chunk by chunk. If I would read it at once, It would not fit into RAM. My unzipped data size is 393 KB If I comment out Block 2, it is working, but I would like to read 512 bytes one after another:

...
#define BUFF_SIZE 512
static uint8_t l_Buff[BUFF_SIZE];
...
    // Block 1
    zip.openCurrentFile();
    mySeek(&myfile, 0, SEEK_SET);
    int readSize = zip.readCurrentFile(l_Buff, BUFF_SIZE);
    Serial.print("Bytes read in buffer: "); Serial.println(readSize);
    binFile.write(l_Buff, BUFF_SIZE);

    // Block 2
    mySeek(&myfile, 512, SEEK_SET);
    readSize = zip.readCurrentFile(l_Buff, BUFF_SIZE);
    Serial.print("Bytes read in buffer: "); Serial.println(readSize);
    binFile.write(l_Buff, BUFF_SIZE);
bitbank2 commented 2 years ago

I need more info to debug this. Can you send me a complete working sample or something that I can try? What output are you getting? What CPU/MCU/OS are you running this code on?

bitbank2 commented 2 years ago

I just updated the Linux example to show what you're trying to do and it worked correctly. If you don't pass it any files, the demo program reads a BMP file from within a ZIP archive in memory. The 2102 byte file is read 256 bytes at a time and it works correctly. Please do a git pull and give it a try.

samsmith94 commented 2 years ago

Thank you! I will try your linux example. I didn't even notice it, as it is not in the example folder.

BTW I think I'm doing pretty much the same, but with the public API. My platform is STM32 F429ZI (Nucleo).

I'm sharing the full source code. Can you see something incorrect?

#include <Arduino.h>
#include <HexDump.h>
#include <unzipLIB.h>
#include "SdFat.h"
#include "sdios.h"

#define BUFF_SIZE 512
static uint8_t l_Buff[BUFF_SIZE];

SPIClass SPI_4(PE6, PE5, PE2); // MOSI, MISO. SCLK
const uint8_t SD_CS_PIN = PE4;
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(4), &SPI_4)

UNZIP zip; // statically allocate the UNZIP structure (41K)
SdFat sd;
File root;

static File myfile;
static File myfileAnother;
static File binFile;

void * myOpen(const char *filename, int32_t *size) {
  root.open("/");
  myfileAnother.open(filename);
  *size = (uint32_t)myfileAnother.fileSize();
  //Serial.print("File size in myOpen: "); Serial.println(*size);

  return (void *)&myfileAnother;
}

void myClose(void *p) {
  ZIPFILE *pzf = (ZIPFILE *)p;
  File *f = (File *)pzf->fHandle;
  if (f) f->close();
}

int32_t myRead(void *p, uint8_t *buffer, int32_t length) {
  ZIPFILE *pzf = (ZIPFILE *)p;
  File *f = (File *)pzf->fHandle;
  return f->read(buffer, length);
}

int32_t mySeek(void *p, int32_t position, int iType) {
  ZIPFILE *pzf = (ZIPFILE *)p;
  File *f = (File *)pzf->fHandle;
  if (iType == SEEK_SET)
    return f->seek(position);
  else if (iType == SEEK_END) {
    return f->seek(position + pzf->iSize); 
  } else { // SEEK_CUR
    long l = f->position();
    return f->seek(l + position);
  }
}

void setup() {
  Serial.begin(115200);

  while (!Serial && millis() < 3000);
  Serial.println("Search for ZIP files on the SD card");

  if (!sd.begin(SD_CONFIG))
  {
    sd.initErrorHalt(&Serial);
    Serial.println("Unable to access SD Card");
  }

  if (!root.open("/"))
  {
    Serial.println("Open root failed");
  }

  if (sd.exists("Folder1"))
  {
    if (sd.exists("Folder1/file1.txt"))
    {
      Serial.println("Folder1/file1.txt is already existing");

      // Change volume working directory to Folder1.
      if (!sd.chdir("Folder1"))
      {
        Serial.println("chdir failed for Folder1.");
      }
      Serial.println("chdir to Folder1");

      // Remove files from current directory.
      if (!sd.remove("file1.txt"))
      {
        Serial.println("remove failed");
      }
      Serial.println("file1.txt removed.");

      // Change current directory to root.
      if (!sd.chdir())
      {
        Serial.println("chdir to root failed.");
      }

      // Remove Folder1.
      if (!sd.rmdir("Folder1"))
      {
        Serial.println("rmdir for Folder1 failed");
      }
      Serial.println("Folder1 removed.");
    }
  }

  //////////////////////////////////////////////////////////////////////////////

  // Create a new folder.
  if (!sd.mkdir("Folder1"))
  {
    Serial.println("Create Folder1 failed");
  }

  if (!sd.mkdir("Folder2"))
  {
    Serial.println("Create Folder2 failed");
  }

  // Create a file in Folder1 using a path.
  if (!myfile.open("Folder1/file1.txt", O_WRONLY | O_CREAT))
  {
    Serial.println("Create Folder1/file1.txt failed");
  }
  Serial.println("Created Folder1/file1.txt");
  myfile.println("Hello 1, 2, 3");
  Serial.println("Hello 1, 2, 3 written to Folder1/file1.txt");

  Serial.print("Size of Folder1/file1.txt: ");
  Serial.println(myfile.fileSize());

  myfile.close();
  Serial.println("Folder1/file1.txt closed");
  Serial.println("****************************************");

  // Create a application.bin file to write RAM to SD card
  if (!binFile.open("application.bin", O_WRONLY | O_CREAT))
  {
    Serial.println("Create application.bin failed");
  }
  else
  {
    Serial.println("application.bin created");
  }

  //////////////////////////////////////////////////////////////////////////////
  int rc;
  char szComment[256], szName[256];
  unz_file_info fi;

  const char *name = "application.zip";
  if (!myfile.open(name, O_RDONLY))
  {
    Serial.println("Opening application.zip failed");
  }
  Serial.println("Openened application.zip");
  rc = rc = zip.openZIP(name, myOpen, myClose, myRead, mySeek);
  if (rc == UNZ_OK) {
    Serial.println("ZIP file found!");

    // Display the global comment and all of the filenames within
    rc = zip.getGlobalComment(szComment, sizeof(szComment));
    Serial.print("Files in this archive: ");
    zip.gotoFirstFile();
    rc = UNZ_OK;
    rc = zip.getFileInfo(&fi, szName, sizeof(szName), NULL, 0, szComment, sizeof(szComment));

    if (rc == UNZ_OK) {
      Serial.println(szName);
      Serial.print("Compressed size: "); Serial.println(fi.compressed_size, DEC);
      Serial.print("Uncompressed size: "); Serial.println(fi.uncompressed_size, DEC);

    }

    // IF THIS LINE IS COMPILED, IT IS NOT WORKING, NOTHING IS PRINTED ON SERIAL CONSOLE
    //zip.locateFile("application.bin");
    zip.openCurrentFile();

    // First block
    int readSize = zip.readCurrentFile(l_Buff, BUFF_SIZE);
    Serial.print("Bytes read into buffer: "); Serial.println(readSize);
    binFile.write(l_Buff, BUFF_SIZE);
    HexDump(Serial, l_Buff, sizeof(l_Buff));

    // IF THIS 4 LINE IS COMPILED, IT IS NOT WORKING, NOTHING IS PRINTED ON SERIAL CONSOLE
    // // Second block
    // readSize = zip.readCurrentFile(l_Buff, BUFF_SIZE);
    // Serial.print("Bytes read into buffer: "); Serial.println(readSize);
    // binFile.write(l_Buff, BUFF_SIZE);
    // HexDump(Serial, l_Buff, sizeof(l_Buff));

    zip.closeCurrentFile();
    zip.closeZIP();

    binFile.close();
  }
}

// Main loop, scan for all .PNG files on the card and display them
void loop() {}
bitbank2 commented 2 years ago

The code looks ok, but the fact that nothing is printed indicates that the system is probably crashing. Have you tried turning on verbose debug mode and seeing what messages are printed on the console?

samsmith94 commented 2 years ago

I cannot even flash a single heartbeat LED 😀 Do have any idea, what could be this? Immediate reset, due to some memory issue?

bitbank2 commented 2 years ago

perhaps the watchdog timer is resetting. Please enable debug output - the CPU will tell you what causes the crash.

samsmith94 commented 2 years ago

I realized, that I had a "hidden" linkerscript in my project folder, so I flashed the application to a wrong starting address. 😡 Thank you for all your help. This is a fantastic library. 👍 I could decompress the 384k zip file as quick as ligthning.