2012-03-25 8 views
5

Dzięki tej stronie i kilku innym, stworzyłem prosty kod do odczytu znaczników ID3v2.3 z plików MP3. Takie podejście było świetnym doświadczeniem, ponieważ wcześniej nie miałem pojęcia o hex/byte/binary itp.Kodowanie tekstu w tagach ID3v2.3

Mogę z powodzeniem odczytać dane, ale natrafiłem na problem, który moim zdaniem ma związek z używanym kodowaniem. Zdałem sobie sprawę, że ramki tekstowe mają bajt na początku "tekstu", który opisuje kodowanie używane, i potencjalnie więcej informacji w następnych 2 bajtach ...

Przykład: Dane z ramki TIT2 zaczynają się od bajtu 03 $ (hex) przed faktycznym tekstem. Ten tekst jest wyświetlany prawidłowo, aczkolwiek z dodatkowym znakiem na początku, przy użyciu kodowania.ASCII.GetString

W innym MP3 dane z TIT2 zaczynają się od $ 01, a po nich następuje $ FF $ FE, co moim zdaniem ma związek z Unicode ? Sam tekst jest jednak podzielony, między znakami tekstu znajduje się $ 00, co uniemożliwia wyświetlanie danych w formularzach Windows (jak tylko napotkamy 00, tekst po prostu się zatrzymuje, więc otrzymuję pierwszą postać i to wszystko). Próbowałem już używać Encoding.UNICODE.GetString, ale to po prostu wydaje się bełkot.

Wydaje się, że drukowanie tych danych na konsoli odbywa się z przerwami między poszczególnymi znakami, więc odczyt danych działa poprawnie.

Czytałem oficjalną dokumentację dla ID3v2.3, ale myślę, że po prostu nie jestem na tyle zorientowany, aby zrozumieć sekcję kodowania tekstu.

Wszelkie odpowiedzi lub linki do artykułów, które mogą być pomocne, będą mile widziane!

Pozdrowienia Ross

Odpowiedz

3

Dane z ramą TIT2 rozpoczyna się od bajtu $ 03 (hex) przed właściwym tekstem. Ten tekst jest wyświetlany prawidłowo, aczkolwiek z dodatkowym znakiem na początku, używając Encoding.ASCII.GetString

Kodowanie 0x03 jest UTF-8, więc należy użyć Encoding.UTF8.GetString. Postać na początku może być znacznikiem kolejności bajtów U + FEFF, który jest używany do rozróżniania między UTF-16LE a UTF-16BE ... to nie ma sensu dla UTF-8, ale narzędzia systemu Windows lubią go tak umieszczać.

UTF-8 to funkcja ID3v2.4 nieobecna w wersji 2.3, co może być przyczyną, dla której nie można jej znaleźć w specyfikacji. W świecie rzeczywistym znajdziesz różne rodzaje bzdur w tagach ID3 niezależnie od wersji.

Dane z TIT2 zaczynają się od $ 01, a po nich następuje FF $ FE, co moim zdaniem ma związek z Unikodem? Sam tekst jest podzielony, ale w każdym znaku tekstowym znajduje się $ 00,

To jest UTF-16LE, kodowanie tekstu na bajt, które system Windows myląco nazywa "Unicode". Składa się z dwubajtowych jednostek kodowych, więc znaki z zakresu U + 0000-U + 00FF wychodzą jako najniższy bajt tego samego numeru, po którym następuje zerowy bajt wysoki. Prefiks 0xFF-0xFE jest prawidłowo używanym znacznikiem kolejności bajtów. Encoding.Unicode.GetString powinien zwrócić prawidłowy ciąg znaków z tego kodu?

wydruk tych danych do konsoli wydaje się działać

Pierwsze znaki spoza ASCII, aby drukować na konsoli systemu Windows może być próba, więc jeśli trafisz problemy pamiętać, mogą one być spowodowane przez sama operacja drukowania.

Dla kompletności, kodowanie 0x02 jest UTF-16BE bez BOM (nie ma wielu powodów, aby to istniało i nigdy nie spotkałem tego w ogóle), a kodowanie 0x00 ma być zgodne z ISO-8859-1 , ale w rzeczywistości może to być praktycznie dowolne kodowanie ASCII-superset, bardziej prawdopodobne jest, że strona kodowa ANSI "Windowsa, taka jak Encoding.GetEncoding(1252) niż standard, jak 8859-1.

+0

Dzięki bobince - dała mi dużo do pracy! – phanteh

0

Świetnie, dostałem kod do odczytu Unicode & ASCII poprawnie (poniżej)!

Jedno pytanie jednak - oczekiwałem, że Encoding.UNICODE.GetString() obsłuży BOM, ale tak się nie wydaje. Rozumiem, że musisz sam przeczytać te bajty. Właśnie usunąłem 2 bajty, jeśli jest to UNICODE poniżej.

public class Frame 
{ 
    FrameHeader _header; 
    public string data; 
    public string name; 


    public Frame(FrameHeader frm, byte[] bytes) 
    { 
     _header = frm; 
     name = _header._name; 
     if (!name.Equals("APIC")) 
     { 
      byte[] actualdata; 
      int y; 
      int x; 
      int encoding = bytes[0]; 

      if (encoding.Equals(1)) 
      { 
       y = 3; 
       actualdata = new byte[bytes.Length - 3]; 
       for (x = 0; x < (bytes.Length - 3); x++, y++) 
        actualdata[x] = bytes[y]; 
       data = Encoding.Unicode.GetString(actualdata); 
      } 
      else 
      { 
       y = 1; 
       actualdata = new byte[bytes.Length - 1]; 
       for (x = 0; x < (bytes.Length - 1); x++, y++) 
        actualdata[x] = bytes[y]; 
       data = Encoding.ASCII.GetString(actualdata); 
      } 
     } 
    } 
} 
5

Wystarczy dodać jeszcze jeden komentarz, kodu kodowania tekstu:

00 - ISO-8859-1 (ASCII).

01 - UCS-2 (kodowany w UTF-16 kod Unicode z BOM), w ID3v2.2 i ID3v2.3.

02 - kodowany w UTF-16BE kod Unicode bez BOM, w ID3v2.4.

03 - Kodowany w UTF-8 kod Unicode, w ID3v2.4.

od: http://en.wikipedia.org/wiki/ID3

+0

Dla kompletności ISO-8859-1 to łacina-1 (ASCII z 0..127 + Europa zachodnia akcentowane znaki z 128..255) https://en.wikipedia.org/wiki/ISO/IEC_8859-1 –

+0

Chociaż nie jest to spec, widziałem tagów UT3 ID3v2.3 (01) bez BOM. Został zakodowany jako UTF-16BE. Nie jestem pewien, czy istnieje jakieś nieoficjalna wartość domyślna, ale Windows i narzędzie innej firmy zdawały się dekodować je poprawnie. – Dustin