Sie tun IO Zeichen-für-Zeichen. Das wird unnötig und schmerzhaft S-L-O-W, sogar mit gepufferten Streams.
Nutzen Sie die Tatsache, dass Ihre Daten in Ihren Dateien als NUL-terminierte Strings gespeichert sind.
Angenommen, Sie sind abwechselnd nul terminierten Strings aus jeder Datei, und auf einer POSIX-Plattform ausgeführt wird, so können Sie einfach mmap()
die Eingabedateien:
typedef struct mapdata
{
const char *ptr;
size_t bytes;
} mapdata_t;
mapdata_t mapFile(const char *filename)
{
mapdata_t data;
struct stat sb;
int fd = open(filename, O_RDONLY);
fstat(fd, &sb);
data.bytes = sb.st_size;
/* assumes we have a NUL byte after the file data
If the size of the file is an exact multiple of the
page size, we won't have the terminating NUL byte! */
data.ptr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
return(data);
}
void unmapFile(mapdata_t data)
{
munmap(data.ptr, data.bytes);
}
void mergeFiles(const char *file1, const char *file2, const char *output)
{
char zeroByte = '\0';
mapdata_t data1 = mapFile(file1);
mapdata_t data2 = mapFile(file2);
size_t strOffset1 = 0UL;
size_t strOffset2 = 0UL;
/* get a page-aligned buffer - a 64kB alignment should work */
char *iobuffer = memalign(64UL * 1024UL, 1024UL * 1024UL);
/* memset the buffer to ensure the virtual mappings exist */
memset(iobuffer, 0, 1024UL * 1024UL);
/* use of direct IO should reduce memory pressure - the 1 MB
buffer is already pretty large, and since we're not seeking
the page cache is really only slowing things down */
int fd = open(output, O_RDWR | O_TRUNC | O_CREAT | O_DIRECT, 0644);
FILE *outputfile = fdopen(fd, "wb");
setvbuf(outputfile, iobuffer, _IOFBF, 1024UL * 1024UL);
/* loop until we reach the end of either mapped file */
for (;;)
{
fputs(data1.ptr + strOffset1, outputfile);
fwrite(&zeroByte, 1, 1, outputfile);
fputs(data2.ptr + strOffset2, outputfile);
fwrite(&zeroByte, 1, 1, outputfile);
/* skip over the string, assuming there's one NUL
byte in between strings */
strOffset1 += 1 + strlen(data1.ptr + strOffset1);
strOffset2 += 1 + strlen(data2.ptr + strOffset2);
/* if either offset is too big, end the loop */
if ((strOffset1 >= data1.bytes) ||
(strOffset2 >= data2.bytes))
{
break;
}
}
fclose(outputfile);
unmapFile(data1);
unmapFile(data2);
}
ich in keinem Fehler gesetzt haben überhaupt zu prüfen. Sie müssen auch die richtigen Header-Dateien hinzufügen.
Beachten Sie auch, dass die Dateidaten zu NOT ein genaues Vielfaches der Systemseitengröße angenommen werden, wodurch sichergestellt wird, dass ein NUL-Byte nach dem Dateiinhalt zugeordnet ist. Wenn die Größe der Datei ein genaues Vielfaches der Seitengröße ist, müssen Sie mmap()
eine zusätzliche Seite nach dem Dateiinhalt, um sicherzustellen, dass es ein NULL-Byte gibt, um die letzte Zeichenfolge zu beenden.
Oder Sie können sich darauf verlassen, dass ein NUL-Byte als letztes Byte des Dateiinhalts vorhanden ist. Wenn sich herausstellt, dass dies nicht der Fall ist, erhalten Sie wahrscheinlich entweder eine SEGV oder beschädigte Daten.
Ich würde zwei Dinge sagen. Zuerst dachte ich, dass 'write' schneller ist als' fwrite'. Zweitens, schreibe nicht jedes einzelne Byte in eine Datei. Machen Sie Ihren eigenen Zwischenpuffer und schreiben Sie große Datenmengen in die Datei. – GMichael
Machen Sie Ihren Code lesbar. – Inline
@GMichael danke für deinen Rat. fwrite sollte gepuffert werden. Denkst du, dass die Funktion, die sich selbst nennt, kritisch ist? –