清理硬盘发现以前写过一个进行一半的代码,这次补全并从硬盘删掉。
格式说明来自 https://shansing.com/read/392/
krc解码并解压缩后得到一个字符串,例子:
[id:$00000000]
[ar:信乐团]
[ti:北京一夜]
[by:韩佯Τé]
[hash:766fe295bf2722a9ede2abdd61d580c1]
[total:278438]
[sign:大家去北京玩一夜吧!!!!]
[53883,3092]<0,632,0>One <632,784,0>Night <1416,372,0>in <1788,548,0>北<2336,755,0>京
[56675,3539]<0,560,0>我<560,416,0>留<976,392,0>下<1368,412,0>许<1780,392,0>多<2172,1366,0>情
[59914,2577]<0,549,0>不<549,276,0>管<825,252,0>你<1077,214,0>爱<1291,182,0>与<1473,212,0>不 <1685,887,0>爱
[62191,3344]<0,560,0>都<560,210,0>是<770,210,0>历<980,204,0>史<1184,202,0>的<1386,564,0>尘<1950,1387,0>埃
开头的几行就不用解释了,lrc也有。
其中快速匹配歌词的可能方式是靠计算歌曲文件的hash,以及匹配歌词与歌曲的total
歌词开始的行格式:
[此行开始时刻距0时刻的毫秒数,此行持续的毫秒数]<0,此字持续的毫秒数,0>歌<此字开始的时刻距此行开始时刻的毫秒数,此字持续的毫秒数,0>词<此字开始的时刻距此行开始时刻的毫秒数,此字持续的毫秒数,0>正<此字开始的时刻距此行开始时刻的毫秒数,此字持续的毫秒数,0>文
具体代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 using System.IO.Compression; 7 using ICSharpCode.SharpZipLib.Zip.Compression; 8 using ICSharpCode.SharpZipLib.Zip.Compression.Streams; 9 using System.Diagnostics; 10 11 namespace KRC.KRCLib 12 { 13 public static class KRCFile 14 { 15 /// <summary> 16 /// 异或加密 密钥 17 /// </summary> 18 public static readonly char[] KRCFileXorKey = { '@', 'G', 'a', 'w', '^', '2', 't', 'G', 'Q', '6', '1', '-', 'Î', 'Ò', 'n', 'i' }; 19 20 /// <summary> 21 /// KRC 文件头 22 /// </summary> 23 public static readonly char[] KRCFileHead = { 'k', 'r', 'c', '1' }; 24 25 /// <summary> 26 /// KRC 文件头的字节 27 /// </summary> 28 public static readonly byte[] KRCFileHeadBytes = { 0x6B, 0x72, 0x63, 0x31 }; 29 30 31 /// <summary> 32 /// 解码 33 /// </summary> 34 public static string DecodeFileToString(string krcFilePath) 35 { 36 //krc1 37 var headBytes = new byte[4]; 38 byte[] encodedBytes; 39 byte[] zipedBytes; 40 41 using (var krcfs = new FileStream(krcFilePath, FileMode.Open)) 42 { 43 encodedBytes = new byte[krcfs.Length - headBytes.Length]; 44 zipedBytes = new byte[krcfs.Length - headBytes.Length]; 45 46 //读文件头标记 47 krcfs.Read(headBytes, 0, headBytes.Length); 48 49 //读XOR加密的内容 50 krcfs.Read(encodedBytes, 0, encodedBytes.Length); 51 52 //关闭文件 53 krcfs.Close(); 54 } 55 56 for (var i = 0; i < encodedBytes.Length; i++) 57 { 58 zipedBytes[i] = (byte)(encodedBytes[i] ^ KRCFileXorKey[i % 16]); 59 } 60 61 //前面3字节是 UTF-8 的 BOM 62 var unzipedBytes = Decompress(zipedBytes); 63 64 //编码器带有BOM输出时多了3字节,所以跳过开头的3字节bom 65 var text = RemoveBom(Encoding.UTF8.GetString(unzipedBytes)); 66 67 return text; 68 } 69 70 /// <summary> 71 /// 编码到字节数组 72 /// </summary> 73 /// <param name="inText"></param> 74 /// <returns></returns> 75 public static byte[] EncodeStringToBytes(string inText) 76 { 77 //用默认的,编码时带有UTF-8的BOM 78 byte[] inbytes = Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(inText)).ToArray(); 79 80 byte[] zipedBytes = Compress(inbytes); 81 82 int encodedBytesLength = zipedBytes.Length; 83 84 var encodedBytes = new byte[zipedBytes.Length]; 85 86 87 for (int i = 0; i < encodedBytesLength; i++) 88 { 89 int l = i % 16; 90 91 encodedBytes[i] = (byte)(zipedBytes[i] ^ KRCFileXorKey[l]); 92 } 93 94 byte[] byets = null; 95 96 using (var ms = new MemoryStream()) 97 { 98 ms.Write(KRCFileHeadBytes, 0, KRCFileHeadBytes.Length); 99 ms.Write(encodedBytes, 0, encodedBytes.Length); 100 ms.Flush(); 101 byets = ms.ToArray(); 102 } 103 104 return byets; 105 } 106 107 /// <summary> 108 /// 移除UTF-8 BOM 109 /// </summary> 110 /// <param name="p"></param> 111 /// <returns></returns> 112 private static string RemoveBom(string p) 113 { 114 string bomMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); 115 if (p.StartsWith(bomMarkUtf8)) 116 p = p.Remove(0, bomMarkUtf8.Length); 117 return p.Replace("