NSString in NSData ( byte )

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NSString in NSData ( byte )

    Hi,
    gibt es einfache weise aus einem NSString was die Rohdaten eines Byte Streams enthält in ein Byte Array zu überführen ?
    Hintergrund, ich bekomme übers Netzwerk Rohdaten von einem Image. Diese möchte ich gerne wieder als Image in der App anzeigen.
    Ich habe somit die Daten bereits korrekt als NSString vorliegen.
    so sieht also der String aus :
    FFD8FFE000104A46494600010101004800480000FFDB0.....

    Jedoch speichere ich den String als Datei auf der Platte ab, und versuche beim einladen daraus ein UIImage zu machen geht das in die Hose.
    Bin für jede Hilfe dankbar.
  • Michael schrieb:

    Sind das wirklich die Rohdaten? Rohdaten könnte man ja direkt in ein NSData Objekt empfangen. Das sieht mir aber eher nach Hexdump aus, also zwei Zeichen gleich ein Byte. So einen Hexdump müsstest Du dann selbst in einen Bytestream umwandeln.


    Stimmt

    FFD8FFE0

    ist das magic key für JPEG.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Hallo,
    danke soweit habe ich verstanden wie es geht.
    @Michael
    dein Hexdump sind meine Rohdaten. :)

    Ich weiß derzeit beim besten willen nicht wie ich aus den 2 Zeichen die ich von dem String je abknapsen muss, ein Byte bekomme.
    habe folgendes versucht :

    Quellcode

    1. filecontent = @"FFD8FFE000104A46494600010101004800480000FFDB0..."
    2. NSMutableData *filebinarycontent= [[NSMutableData alloc] init];
    3. unsigned char bytezeichen;
    4. char byte_chars[2] = {'\0','\0'};
    5. for (int i = 0; i < ([filecontent length] / 2); i++) {
    6. byte_chars[0] = [filecontent characterAtIndex:i*2];
    7. byte_chars[1] = [filecontent characterAtIndex:i*2+1];
    8. bytezeichen = strtol(byte_chars, NULL, 16);
    9. [filebinarycontent appendBytes:&bytezeichen length:1];
    10. }
    11. [filebinarycontent writeToFile:filename atomically:NO];
    Alles anzeigen


    Lade ich diese Datei nun als Image ... ist das image nil :(
    Hat noch jemand ne Idee was ich falsch mache ?
  • @gritsch
    ich würde gerne dazulernen. Könntest du mir sagen, wie ich das ein oder andere verbessern kann ?
    Klar das ich vorab prüfe, ob das filecontent auch durch 2 Teilbar ist kann ich als Sicherung noch mit einbauen. Mehr wüsste ich derzeit noch nicht.
    @Thallius
    leider kann ich wirklich nicht ein "normales" Http Request erzeugen, die Gegenseite ist in Stein gemeißelt. Das einzige was ich habe ist eine raw Socket Kommunikation. Das andere wäre in der Tat schicker.
  • also:

    1. filebinarycontent solltest du gleich mit der korrekten länge initialisieren (da bereits bekannt): hälfte vom input string
    2. byte_chars muss eine länge von 3 haben: char byte_chars[3] = {};
    3. "[filecontent length] / 2" aus der schleife rausnehmen (die zahlt brauchst du öfters, zb auch bei punkt 1)
    4. Nicht characterAtIndex: verwenden sondern vor der schleife die raw daten als ASCII holen (wenn das fehlschlägt dann gleich mit fehler abbrechen)
    5. den zweiten parameter von "strtol" nicht NULL setzen und dann auswerten (um zu sehen ob ungültige werte eignegeben wurden. zb ein "Z")
    6. wenn es sich um sehr große dateien handelt, dann nicht das ergebnis zuerst in den speicher schieben und dann auf die platte schreiben, sondern ohne buffer (bzw nur mit kleinem buffer) auf die platte schreiben - falls nicht bereits die verwendete file-write funktion buffert)
  • Zusätzlich zu gritschs Anmerkungen noch das eine oder andere:

    - Unbedingt die Länge des Strings prüfen. Der muss mindestens 2 Zeichen lang sein (damit die Konvertierung überhaupt klappt - für sinnvolle Bilddateien natürlich mehr).
    - Falls es eine sinnvolle Maximalgröße gibt auch die prüfen.
    - Die Daten kommen von draußen, aus der bösen Welt. Wenn jemand da einen Fehler ausnutzen wollte wären die ersten drei Versuche "sehr wenig (also keine) Daten", "sehr viele Daten", "unsinnige Daten". Das muss abgefangen werden.
    - Große Datenmengen sollte man, wie gritsch schrieb, inkrementell in eine Datei schreiben. Dazu sollte man sie aber auch inkrementell aus dem Netz ziehen und dann on-the-fly in Binärdaten konvertieren. Wenn die Binärdaten nicht in den Speicher passen tut es der Hex-String erst recht nicht, der ist mindestens doppelt so groß.
    - Im Gegensatz dazu kann bei kleinen Datenmengen versuchen, die gar nicht erst in eine Datei zu schreiben, sondern das Bild direkt per initWithData: zu initialisieren. Spart den Umweg über das (langsame) Dateisystem.

    Man könnte noch den strtol rausziehen, aber ich würde nicht versuchen, die Konvertierung bis zur Unkenntlichkeit zu optimieren - die ist eh um Größenordnungen schneller als die Netzverbindung. Da ist lesbarer Code wertvoller. Ich habe eine ähnliche Anwendung (allerdings Android), die einen Livestream mit mehreren MBit pro Sekunde auf diese Weise konvertiert (und das in Java, auf einem elend langsamen Gerät) - die Prozessorlast ist fast zu vernachlässigen.
    Multigrad - 360°-Produktfotografie für den Mac
  • mattik schrieb:

    Zusätzlich zu gritschs Anmerkungen noch das eine oder andere:

    - Unbedingt die Länge des Strings prüfen. Der muss mindestens 2 Zeichen lang sein (damit die Konvertierung überhaupt klappt - für sinnvolle Bilddateien natürlich mehr).
    - Falls es eine sinnvolle Maximalgröße gibt auch die prüfen.
    - Die Daten kommen von draußen, aus der bösen Welt. Wenn jemand da einen Fehler ausnutzen wollte wären die ersten drei Versuche "sehr wenig (also keine) Daten", "sehr viele Daten", "unsinnige Daten". Das muss abgefangen werden.
    - Große Datenmengen sollte man, wie gritsch schrieb, inkrementell in eine Datei schreiben. Dazu sollte man sie aber auch inkrementell aus dem Netz ziehen und dann on-the-fly in Binärdaten konvertieren. Wenn die Binärdaten nicht in den Speicher passen tut es der Hex-String erst recht nicht, der ist mindestens doppelt so groß.
    - Im Gegensatz dazu kann bei kleinen Datenmengen versuchen, die gar nicht erst in eine Datei zu schreiben, sondern das Bild direkt per initWithData: zu initialisieren. Spart den Umweg über das (langsame) Dateisystem.

    Man könnte noch den strtol rausziehen, aber ich würde nicht versuchen, die Konvertierung bis zur Unkenntlichkeit zu optimieren - die ist eh um Größenordnungen schneller als die Netzverbindung. Da ist lesbarer Code wertvoller. Ich habe eine ähnliche Anwendung (allerdings Android), die einen Livestream mit mehreren MBit pro Sekunde auf diese Weise konvertiert (und das in Java, auf einem elend langsamen Gerät) - die Prozessorlast ist fast zu vernachlässigen.


    die länge hat er gesagt prüft er bereits also hab ich das nicht NOCHMAL erwähnt ;)
    strtol hab ich auch gelassen weil das sicher kein problem ergebit.
    die convertierung von NSString zu einem einfachen byte-array wird auch nicht nötig sein weil man von einem raw socket ja keinen NSString bekommt ;)
    arbeitet man immer die daten ab die man vom socket bekommt hat man ja quais di unterteilung in kleinere buffer bereits frei haus.
  • gritsch schrieb:

    die länge hat er gesagt prüft er bereits also hab ich das nicht NOCHMAL erwähnt
    strtol hab ich auch gelassen weil das sicher kein problem ergebit.
    die convertierung von NSString zu einem einfachen byte-array wird auch nicht nötig sein weil man von einem raw socket ja keinen NSString bekommt
    arbeitet man immer die daten ab die man vom socket bekommt hat man ja quais di unterteilung in kleinere buffer bereits frei haus.

    Keine Sorge, ich hätte auch nicht angenommen, dass Du das nicht gewusst oder bedacht hättest :)

    Aber im OP stand, dass die Hex-Daten bereits als NSString bereitstehen, das klang für mich nicht nach inkrementellem Laden. Und der genannte Längentest auf Teilbarkeit durch 2 reicht nicht aus - das ist halt ein beliebter Fehler, deshalb hab' ich es nochmal hingeschrieben. strtol ist mit Sicherheit gut abgehangen, wäre bei mir aber theoretisch ein Optimierungskandidat - zwei Lookups und ein Shift sind halt schneller, zumal man sich dann die Kopiererei in den Temp-Buffer sparen kann. Aber wie gesagt, das würde ich in diesem Fall eben nicht machen, wenn es nicht absolut notwendig wird.
    Multigrad - 360°-Produktfotografie für den Mac