Byte-Daten schreiben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Bulova
User
Beiträge: 8
Registriert: Sonntag 3. August 2025, 12:56

Hallo,
eigentlich habe ich schon Erfahrung beim Programmieren in anderen Sprachen, aber bei Python sehe ich für manche vermeintlich einfache Dinge große Probleme.
Ich möchte Daten aus einer Datei lesen und sie verändert in eine andere schreiben. Es handelt sich um eine WAV-Datei, ich möchte aber das wave.open an dieser Stelle nicht verwenden, u. a. weil es für 24 Bit etwas umständlich ist. Stattdessen würde ich gerne in eine Datei Byte für Byte schreiben:

Code: Alles auswählen

with open(Datei_neu, 'wb') as f:
    for j in range(0,44,1):
        print(j, binary_data[j])
        f.write(bytes(binary_data[j]))
Dies wäre erst einmal für den WAV-Header.
Das ergibt keine Fehlermeldung, aber die Datei ist mit 3 kB viel zu groß und sie beinhaltet lauter Nullwerte, obwohl der Print-Befehl eigentlich ordentliche Werte ausgibt:

0 82
1 73
2 70
3 70
4 36
5 249
...
41 249
42 21
43 0

Ferner musste ich binary.data mit bytes() casten, obwohl an anderer Stelle die Daten <class 'bytes'> ausweisen. Das bringt ohne bytes() aber eine Fehlermeldung, nämlich dass byte erwartet wird aber int geliefert wird.

Gibt es einfache Lösung?

Dieter
Benutzeravatar
__blackjack__
User
Beiträge: 14083
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Bulova: `bytes()` mit einer Zahl aufgerufen macht nicht das was Du denkst:

Code: Alles auswählen

In [197]: bytes(0)
Out[197]: b''

In [198]: bytes(1)
Out[198]: b'\x00'

In [199]: bytes(2)
Out[199]: b'\x00\x00'

In [200]: bytes(3)
Out[200]: b'\x00\x00\x00'

In [201]: bytes(4)
Out[201]: b'\x00\x00\x00\x00'

In [202]: bytes(5)
Out[202]: b'\x00\x00\x00\x00\x00'
Was da also letztlich geschrieben wird ist Summe der Bytewerte = Anzahl der geschriebenen 0-Bytes. Oder als Code ausgedrückt:

Code: Alles auswählen

file_content = b"\x00" * sum(binary_data[:44])
Was den Datentyp angeht: `binary_data` hat den Typ `bytes` aber das schreibst Du ja nicht, Du greifst mit ``binary_data[j]`` auf einzelne Elemente zu und das sind Zahlen vom Typ `int`. Genau das sagt Dir die Fehlermeldung von `write()` ja auch. Glaube den Fehlermeldungen. :-)

Namen in Python übrigens klein_mit_unterstrichen. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase). Das sollte auch nicht Datei heissen, denn es ist ein Datei*name*. Bei einem Objekt mit dem Namen `datei` erwartet der Leser Methoden wie `read()`, `write()`, und `close()`. Dafür darf das `f` gerne als `file` ausgeschrieben werden.

Die 0 als Startwert und die 1 als Schrittweite sind bei `range()` die Voreinstellung, da reicht ``range(44)``.

Aber die ganze Schleife ist eher unsinnig. Man würde einfach `binary_data` direkt schreiben, oder wenn das mehr als die 44 Bytes sind, sliced man den Anfang davon:

Code: Alles auswählen

    with open(filename, "wb") as file:
        file.write(binary_data[:44])
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
Bulova
User
Beiträge: 8
Registriert: Sonntag 3. August 2025, 12:56

Entschudligung, ich hatte nicht geantwortet. Ich hatte jetzt doch alles mit open wave.open erledigen können. Das unpack funktioniert bei 3-Bytes-Frames halt nicht, deshalb sind die einzelnen Bytes gemäß ihrer Wertung zu behandeln und auch 2er-Komplement zu beachten bei vorzeichenbehafteten Daten.
Das funktioniert bereits ordentlich.
Benutzeravatar
__blackjack__
User
Beiträge: 14083
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hast Du Dich schon mal nach existierenden Lösungen umgeschaut? Beispielsweise https://pypi.org/project/wavio/
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
Bulova
User
Beiträge: 8
Registriert: Sonntag 3. August 2025, 12:56

Ja, danke für die Tipps. So einige Feinheiten wie slicing waren mir nicht geläufig, da ich in Python auch eher der blutige Anfänger bin. Wie ich oben schrieb, habe ich das Ganze mit

Code: Alles auswählen

with wave.open(Datei, "rb") as ...
gemacht. Dabei kommt immer die korrekte Frame-Größe heraus (bei 24 Bit also 3 Bytes). Die einzelnen Bytes muss man dann halt isolieren.
Die Verarbeitung der Daten klappt auch, nur ist die Problematik noch eine Menüsteuerung, wie ich in meinem anderen Thread beschrieben habe.
Antworten