2016-06-24 19 views
1

Ich mache eine Codierung Übung und ich muss eine Datei öffnen, die viele Daten enthält. Es ist eine RAW-Datei. Bevor ich meine App erstelle, öffne ich die 'card.raw' Datei in einem Texteditor und in einem Hexeditor. Wenn Sie es in TextEdit öffnen, sehen Sie in der ersten Zeile "bit.ly/18gECvy ÿ JFIFHH € C € C". (Die URL verweist auf Rick Roll als einen Witz des Professors.)C fopen und fgets, die seltsame Zeichen anstelle des Dateiinhalts zurückgeben

Also fange ich an, meine App zu bauen, um die gleiche 'card.raw' Datei zu öffnen. Ich mache erste Überprüfungen, um zu sehen, dass die App die gleichen "Sachen" auf der Konsole ausgibt, als wenn ich sie mit TextEdit öffne. Anstatt zu drucken, sehe ich, wenn ich es mit TextEdit öffne (siehe den Text oben), es beginnt und druckt weiter Text, der so aussieht:

\ 377 \ 304 'u \ 204 \ 206 \ 226 \ 262 \ 302 \ 3227 \ 205 \ 246 \ 266 \ 342GSc \ 224 \ 225 \ 245 \ 265 \ 305 \ 306 \ 325 \ 326Wgs \ 244 \ 346 (w \ 345 \ 362 \ 366 \ 207 \ 264 \ 304 \ 223 \ 227 \ 2678H \ 247 \ 250 \ 343 \ 344 \ 365 \ 377 \ 304

Jetzt habe ich keine Ahnung, was das '\' und die Nummern heißen (nach was suche ich, um mehr zu lesen?), Warum es das stattdessen druckt . das Zeichen (? Unicode) ich sehe, wenn ich in TextEdit öffnen, oder wenn ich diese Ausgabe verhexen oder Unicode umwandeln kann

Mein Code ist:

012.351.
#include <stdio.h> 
    #include <string.h> 
    #include <limits.h> 

    int main(int argc, const char * argv[]) { 

     FILE* file; 

     file = fopen("/Users/jamesgoldstein/CS50/CS50Week4/CS50Recovery/CS50Recovery/CS50Recovery/card.raw", "r"); 

     char output[LINE_MAX]; 

     if (file != NULL) 
     { 
      for (int i = 1; fgets(output, LINE_MAX, file) != NULL; i++) 
      { 
       printf("%s\n", output); 
      } 
     } 

     fclose(file); 

     return 0; 
    } 

AKTUALISIERT & SIMPLIFIED Code fread()

#include <stdio.h> 
#include <string.h> 

int main(int argc, const char * argv[]) { 

    FILE* fp = fopen("/Users/jamesgoldstein/CS50/CS50Week4/CS50Recovery/CS50Recovery/CS50Recovery/card.raw", "rb"); 

    char output[256]; 

    if (fp == NULL) 
    { 
     printf("Bad input\n"); 
     return 1; 
    } 

    for (int i = 1; fread(output, sizeof(output), 1, fp) != NULL; i++) 
    { 
     printf("%s\n", output); 
    } 

    fclose(fp); 

    return 0; 
} 

Ausgang ist teilweise richtig (hier ist ein Ausschnitt von Anfang):

bit.ly/18gECvy

\ 377 \ 330 \ 377 \ 340 \ 221 \ 241 \ 26145 \ 301 \ 321 \ 341 \ "# & 23DE \ 3616BFRTUe \ 202CVbdfrtv \ 222 \ 242 ' u \ 204 \ 206 \ 226 \ 262 \ 302 \ 3227 \ 205 \ 246 \ 266 \ 342GSc \ 224 \ 225 \ 245 \ 265 \ 305 \ 306 \ 325 \ 326Wgs \ 244 \ 346 (w \ 345 \ 362 \ 366 \ 207 \ 264 \ 304 | \ 223 \ 227 \ 2678H \ 247 \ 250 \ 343 \ 344 \ 365 \ 377 \ 304 = \ 311 \ 345 \ 264 \ 352 \ 354 7 \ 222 \ 315 \ 306 \ 324 + \ 342 \ 364 \ 273 \ 274 \ 205 $ z \ 262 \ 313g- \ 343wl \ 306 \ 375My:} \ 242o \ 210 \ 377 3 (\ 266l \ 356 \ 307T \ "2 \ 377 \ 267 \ 212 \ P \ 2218 \ 344

Actual card.raw Datei snippet Anfang

bit.ly/18gECvy ÿ ‡ JFIFHH € C € C¿Vƒ
ƒÖ
! 1AQa $% QAe ° ± 45¡- · "# & 23DEÒ6BFRTUeÇCVbdfrtví ¢

+0

Sie sehen aus wie Escape-Sequenzen für Sonderzeichen – edhurtig

+2

Auch, weil dies eine '.rtf' Datei ist, wird es seltsam sein. Verwenden Sie nicht Textedit, um den Inhalt der Datei zu verifizieren, da die RAW-Daten in vorzeigbare Informationen konvertiert werden. Öffnen Sie Terminal und 'cat/Benutzer/jamesgoldstein/CS50/CS50Week4/CS50Recovery/CS50Recovery/CS50Recovery/test.rtf' und Sie sollten das gleiche sehen, was Ihr Programm tut – edhurtig

+0

Die RTF-Datei war ein Test, die eigentliche Datei ist .raw. Ich habe gerade den Code korrigiert. –

Antwort

1

Sie sollten wahrscheinlich fread anstatt fgets verwenden, da letzteres wirklich für das Lesen von Textdateien gedacht ist, und dies ist eindeutig keine Textdatei.

Ihre aktualisierte Code tatsächlich funktioniert das sehr Problem habe ich ursprünglich über schrieb (aber seitdem zurückgezogen), da Sie jetzt verwenden fread statt fgets:

for (int i = 1; fread(output, sizeof(output), 1, fp) != NULL; i++) 
{ 
    printf("%s\n", output); 
} 

D.h. Sie drucken den Puffer output, als ob es eine Null-terminierte Zeichenfolge wäre, obwohl dies tatsächlich nicht der Fall ist. Besser zu verwenden fwrite zu STDOUT.

Ich denke jedoch, das Wesen des Problems hier versucht, beliebige Bytes (die eigentlich keine Zeichenkette darstellen) auf dem Terminal anzuzeigen. Das Terminal kann einige Bytefolgen als Befehle interpretieren, die sich darauf auswirken, was Sie sehen. Außerdem kann textEdit feststellen, dass die Datei in einigen Zeichencodierungs- und Decodierzeichen entsprechend ist. Jetzt

Ich habe keine Ahnung, was das ‚\‘ und Zahlen genannt werden (was suche ich mehr lesen?)

Sie sehen aus wie Oktal-Escape-Sequenzen zu mir.

warum er den Druck ist, dass anstelle der Zeichen (Unicode?)

Es ist nichts mit Unicode zu tun. Vielleicht entscheidet Ihr Terminal-Emulator, dass diese Zeichen nicht druckbar sind, und ersetzt sie durch eine Escape-Sequenz.

Kurz gesagt, denke ich, dass Ihre Methode (Vergleich visuell, was Sie in einem Texteditor mit was Sie auf dem Terminal sehen) fehlerhaft ist. Der Code, den Sie aus der Datei lesen müssen, sieht korrekt aus. Ich würde vorschlagen, mit der Übung fortzufahren und die Ergebnisse zu überprüfen, oder wenn Sie wirklich sicher sein wollen, sehen Sie sich die Datei mit einem Hex-Editor an und lassen Sie Ihr Programm die Bytewerte ausgeben (als Zahlen) - und vergleichen Sie diese mit was Sie im Hex-Editor sehen.

+2

'fgets' ist in Ordnung. Es fügt ein abschließendes Nullbyte hinzu. Tatsächlich ist 'fgets' eine Standardmethode zum Lesen von Textdateien Zeile für Zeile. –

+0

@ Alok-- du hast natürlich Recht. Ich habe mich nicht erinnert. Ich habe diesen Teil bearbeitet, könnte aber die Antwort in Kürze löschen. – davmac

+0

@ Alok-- (außer natürlich, dass die Datei ist _not_ eine Textdatei, und ist nicht unbedingt in Zeilen, und der aktualisierte Code verwendet 'fread' statt' fgets' und so _is_ abhängig von dem Problem. Ich habe entsprechend bearbeitet). – davmac

1

Von der Anwesenheit des Strings "JFIF" in der ersten Zeile der Datei card.raw („bit.ly/18gECvy ÿ ‡ JFIFHH € C € C¿Vƒ“) scheint es, wie card.raw eine Datei Bildformat JPEG ist, dass das hatte bit.ly URL am Anfang eingefügt.

Sie werden seltsame/Sonderzeichen in diesem Fall sehen, weil es überhaupt keine übliche Textdatei ist.

Auch, wie davmac darauf hingewiesen, ist die Art und Weise, wie Sie fgets verwenden, nicht geeignet, auch wenn Sie mit einer tatsächlichen Textdatei beschäftigt waren. Wenn Sie mit Textdateien in C tun hat, ist der beste Weg, um die gesamte Datei auf einmal statt Zeile für Zeile zu lesen, ausreichend Speicher unter der Annahme zur Verfügung:

size_t f_len, f_actualread; 

char *buffer = NULL; 

fseek(file, 0, SEEK_END) 
f_len = ftell(fp); 
rewind(fp); 

buffer = malloc(f_len + 1); 

if(buffer == NULL) 
{ 
    puts("malloc failed"); 
    return; 
} 

f_actualread = fread(buffer, 1, f_len, file); 
buffer[f_actualread] = 0; 

printf("%s\n", output); 

free(buffer); 
buffer = NULL; 

Auf diese Weise brauchen Sie keine Sorgen zu machen Leitungslängen oder ähnliches.

+0

Eigentlich ist 'fgets' in Ordnung, um Textdateien zu lesen. Es terminiert die Daten immer auf Null. –

+1

@ Alok-- Ich denke, der Punkt hier war, dass ist _istnot_ eine Textdatei. – davmac

2

Ich denke, Sie sollten die .raw-Datei im Modus "rb" öffnen. Dann verwenden fread()

+0

Ok, viel näher! Habe ein Teil der Datei durchkommen lassen und einige davon als/###/###/####. –

+0

Überprüfen Sie meinen aktualisierten Code und die Ausgabe. Vielen Dank! –

+0

@JamesGoldstein 'fread' gibt dir keine Zeichenfolge. Sie können es nicht einfach an 'printf''% s' übergeben. – melpomene