Domanda

Sto tentando di portare un piccolo programma di analisi dei dati da un sistema UNIX a 64 bit a un sistema Windows XP a 32 bit (non chiedere :)). Ma ora sto riscontrando problemi con il limite di dimensioni del file da 2 GB (a lungo non è 64 bit su questa piattaforma).

Ho cercato a questo sito Web e ad altri possibili luci ma non riesco a trovare nessuno che sia direttamente traducibile nel mio problema. Il problema è l'uso di Fseek e Ftell.

Qualcuno sa di una modifica alle seguenti due funzioni per farle funzionare su Windows XP a 32 bit per file più grandi di 2 GB (in realtà ordina 100 GB).

È fondamentale che il tipo di ritorno di nsamples sia un numero intero a 64 bit (possibilmente int64_t).

long nsamples(char* filename)
{
  FILE *fp;
  long n;

  /* Open file */
  fp = fopen(filename, "rb");

  /* Find end of file */
  fseek(fp, 0L, SEEK_END);

  /* Get number of samples */
  n = ftell(fp) / sizeof(short);

  /* Close file */
  fclose(fp);

  /* Return number of samples in file */
  return n;
}

e

void readdata(char* filename, short* data, long start, int n)
{
  FILE *fp;

  /* Open file */
  fp = fopen(filename, "rb");

  /* Skip to correct position */
  fseek(fp, start * sizeof(short), SEEK_SET);

  /* Read data */
  fread(data, sizeof(short), n, fp);

  /* Close file */
  fclose(fp);
}

Ho provato a usare _fseeki64 e _ftelli64 usando quanto segue per sostituire i nsampli:

__int64 nsamples(char* filename)
{
  FILE *fp;
  __int64 n;
  int result;

  /* Open file */
  fp = fopen(filename, "rb");
  if (fp == NULL)
  {
    perror("Error: could not open file!\n");
    return -1;
  }

  /* Find end of file */
  result = _fseeki64(fp, (__int64)0, SEEK_END);
  if (result)
  {
    perror("Error: fseek failed!\n");
    return result;
  }

  /* Get number of samples */
  n = _ftelli64(fp) / sizeof(short);

  printf("%I64d\n", n);

  /* Close file */
  fclose(fp);

  /* Return number of samples in file */
  return n;
}

per un file di 4815060992 byte ottengo 260046848 campioni (ad es _ftelli64520093696 byte) che è strano.

Curiosamente quando lascio fuori il (__int64) cast nella chiamata a _fseeki64 Ricevo un errore di runtime (argomento non valido).

Qualche idea?

È stato utile?

Soluzione 2

Ci scusiamo per non aver pubblicato prima, ma sono stato preoccupato per altri progetti per un po '. La seguente soluzione funziona:

__int64 nsamples(char* filename)
{
  int fh;
  __int64 n;

  /* Open file */
  fh = _open( filename, _O_BINARY );

  /* Find end of file */
  n = _lseeki64(fh, 0, SEEK_END);

  /* Close file */
  _close(fh);

 return n / sizeof(short);
}

Il trucco stava usando _open invece di fopen Per aprire il file. Ancora non capisco esattamente perché questo debba essere fatto, ma almeno ora funziona. Grazie a tutti per i tuoi suggerimenti che alla fine mi hanno indicato nella giusta direzione.

Altri suggerimenti

Ci sono due funzioni chiamate _fseeki64 e _ftelli64 che supportano gli offset di file più lunghi anche su Windows a 32 bit:

int _fseeki64(FILE *stream, __int64 offset, int origin);

__int64 _ftelli64(FILE *stream);

Il mio BC dice:

520093696 + 4294967296 => 4815060992

Immagino che la tua routine di stampa sia a 32 bit. Il tuo offset restituito è molto probabilmente corretto ma essere tagliato da qualche parte.

E per GCC, vedi così domanda 1035657. Laddove il consiglio è compilato con il flag -d_file_offset_bits = 64 in modo che le variabili nascoste (di tipo off_t) usate dalle funzioni f-move-around siano (sono) 64 bit.

Per MINGW: "il supporto di grandi dimensioni (LFS) è stato implementato ridefinendo le funzioni e i tipi di statistica e cerchi ai loro equivalenti a 64 bit. Per Fseek e Ftell, versioni LFS separate, Fseeko e Ftello, basate su FsetPos e FgetPos, sono fornito in Libgw32c." (riferimento). Nelle versioni recenti di GCC, Fseeko e Ftello sono integrate e non è necessaria una libreria separata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top