Tôi đang tìm kiếm thẻ id3 trong tệp bài hát. Một tệp có thể có thẻ mở rộng id3v1, id3v1 (nằm ở cuối tệp) cũng như thẻ id3v2 (thường nằm ở đầu). Đối với các thẻ id3v1, tôi có thể sử dụng File.read (song_file) và kéo ra 355 byte cuối cùng (128 + 227 cho thẻ mở rộng). Tuy nhiên, đối với các thẻ id3v2, tôi cần phải tìm kiếm thông qua các tập tin từ đầu tìm kiếm một mẫu id3v2 10 byte. Tôi muốn tránh bất kỳ chi phí nào từ việc mở và đóng cùng một tệp khi tôi tìm kiếm các thẻ khác nhau, vì vậy tôi nghĩ cách tốt nhất là sử dụng File.stream! (Song_file) và gửi luồng tệp đến các chức năng khác nhau để tìm kiếm các thẻ khác nhau.Cách hiệu quả nhất để tìm kiếm tệp mẫu byte trong Elixir
def parse(file_name) do
file_stream = File.stream!(file_name, [], 1)
id3v1_tags(file_stream)
|> add_tags(id3v2_tags(file_stream))
end
def id3v1_tags(file_stream) do
tags = Tags%{} #struct containing desired tags
<< id3_extended_tag :: binary-size(227), id3_tag :: binary-size(128) >> = Stream.take(file_stream, -355)
id3_tag = to_string(id3_tag)
if String.slice(id3_tag,0, 3) == "TAG" do
Map.put(tags, :title, String.slice(id3_tag, 3, 30))
Map.put(tags, :track_artist, String.slice(id3_tag, 33, 30))
...
end
if String.slice(id3_extended_tag, 0, 4) == "TAG+" do
Map.put(tags, :title, tags.title <> String.slice(id3_extended_tag, 4, 60))
Map.put(tags, :track_artist, tags.track_artist <> String.slice(id3_extended_tag, 64, 60))
...
end
end
def id3v2_tags(file_stream) do
search for pattern:
<<0x49, 0x44, 0x33, version1, version2, flags, size1, size2, size3, size4>>
end
1) Tôi có lưu bất kỳ thời gian chạy nào bằng cách tạo File.stream không! một lần và gửi nó đến các chức năng khác nhau (tôi sẽ quét hàng chục ngàn tập tin, vì vậy tiết kiệm một chút thời gian là quan trọng)? Hoặc tôi chỉ nên sử dụng File.read cho các thẻ id3v1 và File.stream! cho các thẻ id3v2?
2) Tôi nhận được một lỗi trong dòng:
<< id3_extended_tag :: binary-size(227), id3_tag :: binary-size(128) >> = Stream.take(file_stream, -355)
vì Stream.take (file_stream, -355) là một chức năng, không phải là một nhị phân. Làm cách nào để biến nó thành dạng nhị phân mà tôi có thể khớp mẫu?
Tôi không có câu trả lời cho bạn nhưng nếu tôi là bạn, tôi thực sự sẽ tránh được số ma thuật. Tôi giả định -355 là tổng của 128 và 227? Nếu tôi là bạn tôi muốn đặt một thuộc tính mô-đun gọi là '@ id_extended_tag_binsize' thành 227 và' @ id3_tag_binsize' thành 128 và sau đó sử dụng các thuộc tính đó trong Stream.take như sau: Stream.take (file_stream, - ('@ id_extended_tag_binsize' + '@ id3_tag_binsize')) Dễ bị lỗi và dễ đọc hơn nhiều. –
Trước hết, File.stream cần được thông báo để đọc byte thay vì các dòng sử dụng cú pháp File.stream! (Đường dẫn, [: đọc],: byte). Tiếp theo, tôi không nghĩ rằng -355 có thể được sử dụng với Stream.take vì luồng không phải là danh sách mà là danh sách tiềm năng cần được hoàn thành với lệnh gọi Stream.to_list. – GavinBrelstaff
Cảm ơn các đề xuất. Tôi đã thay đổi mã của mình cho phù hợp. –