Wie soll ich in C eine Textdatei lesen und alle Zeichenfolgen drucken?
Lesezeit: 7 Minuten
richardaum
Ich habe eine Textdatei mit dem Namen test.txt
Ich möchte ein C-Programm schreiben, das diese Datei lesen und den Inhalt auf der Konsole ausgeben kann (vorausgesetzt, die Datei enthält nur ASCII-Text).
Ich weiß nicht, wie ich die Größe meiner String-Variablen erhalte. So was:
Die Größe 999 funktioniert nicht, weil die von zurückgegebene Zeichenfolge fscanf kann größer sein. Wie kann ich das lösen?
Am einfachsten ist es, ein Zeichen zu lesen und direkt nach dem Lesen zu drucken:
int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
c ist int oben, da EOF ist eine negative Zahl und eine Ebene char vielleicht unsigned.
Wenn Sie die Datei in Blöcken lesen möchten, aber ohne dynamische Speicherzuweisung, können Sie Folgendes tun:
#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;
file = fopen("test.txt", "r");
if (file) {
while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
fwrite(buf, 1, nread, stdout);
if (ferror(file)) {
/* deal with error */
}
fclose(file);
}
Die zweite Methode oben ist im Wesentlichen, wie Sie eine Datei mit einem dynamisch zugewiesenen Array lesen:
char *buf = malloc(chunk);
if (buf == NULL) {
/* deal with malloc() failure */
}
/* otherwise do this. Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
/* as above */
}
Ihre Methode der fscanf() mit %s da das Format Informationen über Leerzeichen in der Datei verliert, kopiert es nicht genau eine Datei in stdout.
Es ist möglich, Daten aus einer Datei zu lesen, ohne diese Datei in c/c++ zu öffnen??
– Sagar Patel
27. Oktober 2015 um 11:13 Uhr
Was ist, wenn die Textdatei durch Kommas getrennte Ganzzahlwerte enthält? Als was wäre der Code, können Sie Ihre Antwort auch damit bearbeiten.
– Mohsin
21. Oktober 2016 um 20:43 Uhr
Das obige funktioniert für jede Art von Textdatei. Wenn Sie die Zahlen aus einer CSV-Datei analysieren möchten, ist das ein anderes Problem.
– Alok Singhal
22. Oktober 2016 um 3:34 Uhr
@overexchange Die Frage spricht nicht über Zeilen – es geht darum, eine Datei zu lesen und ihren Inhalt zu kopieren stdout.
– Alok Singhal
3. Januar 2017 um 3:35 Uhr
@shjeff Eine Datei darf kein EOF-Zeichen enthalten. Beachten Sie, dass c ist int, und C wird das garantieren EOF ist keinem gültigen Zeichen gleich.
– Alok Singhal
22. November 2017 um 22:14 Uhr
lfzawacki
Hier gibt es viele gute Antworten zum Lesen in Blöcken. Ich zeige Ihnen nur einen kleinen Trick, der den gesamten Inhalt auf einmal in einen Puffer liest und ausgibt.
Ich sage nicht, dass es besser ist. Ist es nicht, und wie bei Ricardo kann es manchmal schlecht sein, aber ich finde es ist eine nette Lösung für die einfachen Fälle.
Ich habe es mit Kommentaren gesprenkelt, weil viel los ist.
#include <stdio.h>
#include <stdlib.h>
char* ReadFile(char *filename)
{
char *buffer = NULL;
int string_size, read_size;
FILE *handler = fopen(filename, "r");
if (handler)
{
// Seek the last byte of the file
fseek(handler, 0, SEEK_END);
// Offset from the first to the last byte, or in other words, filesize
string_size = ftell(handler);
// go back to the start of the file
rewind(handler);
// Allocate a string that can hold it all
buffer = (char*) malloc(sizeof(char) * (string_size + 1) );
// Read it all in one operation
read_size = fread(buffer, sizeof(char), string_size, handler);
// fread doesn't set it so put a \0 in the last position
// and buffer is now officially a string
buffer[string_size] = '\0';
if (string_size != read_size)
{
// Something went wrong, throw away the memory and set
// the buffer to NULL
free(buffer);
buffer = NULL;
}
// Always remember to close the file.
fclose(handler);
}
return buffer;
}
int main()
{
char *string = ReadFile("yourfile.txt");
if (string)
{
puts(string);
free(string);
}
return 0;
}
Lassen Sie mich wissen, ob es nützlich ist oder Sie etwas daraus lernen könnten 🙂
Sollte es nicht lesen buffer[string_size] = '\0'; Anstatt von string_size+1? Afaik der eigentliche String geht aus 0 zu string_size-1 und die \0 Charakter muss also sein string_sizeRechts?
Eine Sache, die Sie unter Windows beachten sollten, string_size möglicherweise nicht gleich read_size wenn die Datei im Textmodus geöffnet wird. Ich zitiere aus diesem Link (bytes.com/topic/c/answers/479976-interesting-thing-about-fread) Under Windows, a text file has two characters for end-of-line (CR+LF -- "\r\n"), but the C library will strip the CR when reading a file open in text mode, so that the program will only see LF ('\n'). The stat() call is returning the "real" size if the file, while the returns from fread() have stripped the CR.
– Ärger
7. September 2015 um 0:45 Uhr
Dieser Code enthält ein Speicherleck, Sie schließen die Datei nie. Es fehlt ein fclose(handle)
– Joakim
10. April 2016 um 22:16 Uhr
Du könntest benutzen calloc(2) statt malloc(1) um zu überspringen, dass der Null-Terminator gesetzt werden muss.
– Benutzer376845
7. Februar 2018 um 7:55 Uhr
Sagar Schah
Geben Sie die Zeichen stattdessen einfach direkt auf der Konsole aus, da die Textdatei möglicherweise sehr groß ist und Sie möglicherweise viel Speicher benötigen.
Die Funktion read() soll versuchen zu lesen nbyte Bytes aus der Datei, die dem offenen Dateideskriptor zugeordnet ist, fildesin den Puffer, auf den gezeigt wird buf.
Sie können verwenden fgets und begrenzen Sie die Größe des gelesenen Strings.
char *fgets(char *str, int num, FILE *stream);
Sie können die ändern while in deinem Code an:
while (fgets(str, 100, file)) /* printf("%s", str) */;
RBerteig
Zwei Ansätze fallen mir spontan ein.
Erstens nicht verwenden scanf. Verwenden fgets() die einen Parameter akzeptiert, um die Puffergröße anzugeben, und die alle Zeilenumbruchzeichen intakt lässt. Eine einfache Schleife über die Datei, die den Pufferinhalt druckt, sollte die Datei natürlich intakt kopieren.
Zweitens verwenden fread() oder das gebräuchliche C-Idiom mit fgetc(). Diese würden die Datei in Blöcken fester Größe oder jeweils ein einzelnes Zeichen verarbeiten.
Wenn Sie die Datei über durch Leerzeichen getrennte Zeichenfolgen verarbeiten müssen, verwenden Sie eine von beiden fgets oder fread um die Datei zu lesen, und so etwas strtok um den Puffer bei Leerzeichen aufzuteilen. Vergessen Sie nicht, den Übergang von einem Puffer zum nächsten zu handhaben, da Ihre Zielzeichenfolgen wahrscheinlich die Puffergrenze überspannen.
Wenn eine externe Anforderung zur Verwendung besteht scanf Um den Lesevorgang durchzuführen, begrenzen Sie dann die Länge der möglicherweise gelesenen Zeichenfolge mit einem Genauigkeitsfeld im Formatbezeichner. In Ihrem Fall mit einem 999-Byte-Puffer, sagen Sie dann scanf("%998s", str); Dadurch werden höchstens 998 Zeichen in den Puffer geschrieben, sodass Platz für das Null-Terminator bleibt. Wenn einzelne Zeichenfolgen länger als Ihr Puffer zulässig sind, müssen Sie sie in zwei Teilen verarbeiten. Wenn nicht, haben Sie die Möglichkeit, den Benutzer höflich über einen Fehler zu informieren, ohne eine Pufferüberlauf-Sicherheitslücke zu erzeugen.
Unabhängig davon sollten Sie immer die Rückgabewerte validieren und darüber nachdenken, wie Sie mit fehlerhaften, böswilligen oder einfach falsch formatierten Eingaben umgehen.