Считать определённое количество данных по определённому смещению. Разбор ID3v2 mp3 тегов - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Работаю с mp3 тегами. Задача - считать определённое количество данных по определённому смещению. Если при считывании тегов версии ID3v1 проблем не возникает, так как данные идут друг за другом и имеют фиксированный размер,то в версии V2 всё иначе. Теги имеют различную длину и как-то хитро записаны в mp3 файл. Во втором случае теги начинаются с определённого фрейма (в моём случае COMM) (4 байта). Потом идёт размер в байтах (выделено 4 байта). Потом ещё какая-то информация //Кто знает..подскажите. И потом собственно само описание фрейма. Если посмотреть на скриншот то информация записана в немного изменённом виде. Буквы чередуются с 0x00 байтами. Считываю я это всё так
fread(&name,length,1,file);
Где собственно length и есть длина строки с описанием. В hex вывожу так
static void hex_print(const void* pv, size_t len)
{
    const unsigned char * p = (const unsigned char*)pv;
    if (NULL == pv)
        printf("NULL");
    else
    {
        size_t i = 0;
        for (; i<len;++i){
             printf("%02X ", *p++);}
 
    printf("%s",*p);
    printf("\n");
}
Мне нужно удалить 0x00 байты из данной последовательности. Понятное дело..можно сделать и так
    for(int i=0;i<sizeof(name)-1;i++){
        if (name[i]==0){
            for (int j=i;j<sizeof(name)-1;j++){
                name[j]=name[j+1];
                name[j+1]=0;
            }
        }
    }
но мне нужно это дело провернуть в HEX. а с HEX я не очень.
Прошу пример кода,где можно удалить из строки определённые байты.
второй вопрос
как мне из последовательности байт..допустим 00 00 00 44. Получить значение типа Int?

Решение задачи: «Считать определённое количество данных по определённому смещению. Разбор ID3v2 mp3 тегов»

textual
Листинг программы
#include <stdio.h>
#include <netinet/in.h> // нужна для ntohl() под Windows заменить на WinSock2.h
 
int main() {
    unsigned char buff[] = {
        0x43,0x4F,0x4D,0x4D, // COMM
        0x00,0x00,0x00,0x1D, // block length
        0x00,0x00,           // \0\0
        0x03,0x65,0x6E,0x67,0x00, // \x03eng\0
        0x28,0x45,0x64,0x69,0x74,0x29,0x20,0x5B,
        0x32,0x30,0x31,0x31,0x20,0x2D,0x20,0x52,
        0x65,0x6D,0x61,0x73,0x74,0x65,0x72,0x5D,
        0x00
    };
 
    char * p = (char*) buff;
 
    printf("chunk = '%s'\n", p);
    p += 4;
 
    printf("block length = %d\n", ntohl(*((uint32_t*)p)));
    p += 4 + 2;
 
    printf("subblock length = %d\n", *p);
 
    printf("lang = '%s'\n", &p[1]);
    p += *p + 1 + 1;
 
    printf("comment = '%s'\n", p);
 
    return 0;
}

Объяснение кода листинга программы

  1. Включаем необходимые заголовочные файлы:

    include

    include <netinet/in.h>

  2. Объявляем основную функцию программы: int main()
  3. Создаём массив данных: unsigned char buff[] = { 0x43,0x4F,0x4D,0x4D, // COMM 0x00,0x00,0x00,0x1D, // block length 0x00,0x00, 0x03,0x65,0x6E,0x67,0x00, // \x03eng\0 0x28,0x45,0x64,0x69,0x74,0x29,0x20,0x5B, 0x32,0x30,0x31,0x31,0x20,0x2D,0x20,0x52, 0x65,0x6D,0x61,0x73,0x74,0x65,0x72,0x5D, 0x00 };
  4. Объявляем указатель на начало массива: char p = (char) buff;
  5. Выводим значение первого поля: printf(chunk = '%s'\n, p); p += 4;
  6. Выводим значение второго поля: printf(block length = %d\n, ntohl(((uint32_t)p))); p += 4 + 2;
  7. Выводим значение третьего поля: printf(subblock length = %d\n, *p);
  8. Выводим значение четвёртого поля: printf(lang = '%s'\n, &p[1]); p += *p + 1 + 1;
  9. Выводим значение пятого поля: printf(comment = '%s'\n, p);
  10. Завершаем работу программы: return 0;

Оцени полезность:

7   голосов , оценка 3.714 из 5
Похожие ответы