// Import the necessary namespaces for file handling
using System;
using System.IO;
using System.Text;
class MP3Reader
{
// Main method where the program starts
static void Main(string[] args)
{
// Ensure the user provided the correct number of arguments
if (args.Length != 1)
{
Console.WriteLine("Usage: MP3Reader ");
return;
}
string mp3File = args[0];
// Check if the file exists
if (!File.Exists(mp3File))
{
Console.WriteLine("Error: The file does not exist.");
return;
}
try
{
// Open the MP3 file in read-only mode
using (FileStream fs = new FileStream(mp3File, FileMode.Open, FileAccess.Read))
{
// Move to the last 128 bytes where the ID3v1 tag is located
fs.Seek(-128, SeekOrigin.End);
// Read the last 128 bytes into a buffer
byte[] tagBuffer = new byte[128];
fs.Read(tagBuffer, 0, 128);
// Check if the tag header is "TAG" (ID3v1 header identifier)
string tagHeader = Encoding.ASCII.GetString(tagBuffer, 0, 3);
if (tagHeader != "TAG")
{
Console.WriteLine("No ID3v1 tag found in this MP3 file.");
return;
}
// Extract the information from the ID3v1 tag
string title = TrimString(Encoding.ASCII.GetString(tagBuffer, 3, 30));
string artist = TrimString(Encoding.ASCII.GetString(tagBuffer, 33, 30));
string album = TrimString(Encoding.ASCII.GetString(tagBuffer, 63, 30));
string year = TrimString(Encoding.ASCII.GetString(tagBuffer, 93, 4));
string comment = TrimString(Encoding.ASCII.GetString(tagBuffer, 97, 30));
// Genre is stored as a byte, so we read it and map it to a genre
byte genreByte = tagBuffer[127];
string genre = GetGenreName(genreByte);
// Display the extracted information
Console.WriteLine("ID3v1 Tag Information:");
Console.WriteLine($"Title: {title}");
Console.WriteLine($"Artist: {artist}");
Console.WriteLine($"Album: {album}");
Console.WriteLine($"Year: {year}");
Console.WriteLine($"Comment: {comment}");
Console.WriteLine($"Genre: {genre}");
}
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
// Helper function to trim trailing spaces from strings
static string TrimString(string input)
{
return input.TrimEnd('\0', ' ');
}
// Helper function to map genre byte to genre name
static string GetGenreName(byte genreByte)
{
// 80 predefined genres from the ID3v1 specification
string[] genres = new string[]
{
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop",
"Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae",
"Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
"Soundtrack", "Euro-Techno", "Pop-Folk", "Pop-Funk", "Fusion", "Trance", "Video",
"Rock & Roll", "Hard Rock", "Alternative Rock", "Christian", "Country Rock",
"Dance Hall", "Death Metal", "Disco House", "Eurodance", "Groove", "House",
"Indie", "Minimal", "Reggaeton", "Techno Trance", "Hardcore", "Dubstep", "Trap",
"Ambient", "Chill-out", "House Techno", "Synthwave", "Nu Disco", "Electro",
"Future Bass", "Deep House", "Indie Dance", "Funk", "Folk", "Reggae Dub", "Jazz Funk",
"K-Pop", "J-Pop", "Blues Rock", "Soul", "Acoustic", "Folk Rock", "Gospel", "Pop Rock",
"Soul", "Folk", "Punk", "Post Punk", "Ska Punk", "Riot Grrl", "Country Blues", "Blues Rock",
"Latin Jazz", "Experimental", "Avant-garde", "Jazzy Funk", "Electropop", "Acid Jazz",
"Post-Rock", "Noise", "Jazz Rock", "Math Rock", "Psychedelic Rock", "Pop Punk",
"Southern Rock", "Folk Punk", "Indie Pop", "Jazz Blues", "Folk Soul", "Indie R&B",
"Blues Soul", "Electro-Rock", "Garage Rock"
};
// Return the genre name based on the genre byte
if (genreByte >= 0 && genreByte < genres.Length)
{
return genres[genreByte];
}
else
{
return "Unknown";
}
}
}