
1,读取
我们需要外接一个NFC Reader让Windows可以读取NFC卡片的内容。
因为特殊原因,我们选择了Sony rc-s380 NFC Reader。相关介绍
我们需要下载并安装NFC Port Software,以便我们可以顺利使用上述NFC Reader。
安装之后,我们需要去Github获取一个NFC Port Software的.Net封装包:tijins/NfcLib
解压并运行nfc_lib_sample之后我们可以看到这样一个WindowFrom程序。
因为现在要读取的卡类型试MIFARE,缺含裂所以我们勾选正确的CheckBox,其他设置保持不变,依次点击上述三个橘色方框按钮。
在红色箭头所指的方向就能看到第一个block的十六进制字符串的数据。
为了读取卡片所有block/page的信息,我们将btRead_Click的代码稍稍修改为:
private void btRead_Click(object sender, EventArgs e)
{
byte block = (byte)nudBlock.Valuetry{byte[] data = null
data = new byte[NfcLib.MF_BLOCK_LENGTH]if (card is Mifare)
{
StringBuilder readSB = new StringBuilder()for(byte i=0i <45i++)//我现在的卡包含45个blocks/pages{
((Mifare)card).Read(i, data, 0)
readSB.AppendLine(Utility.ByteToHex(data, 0, data.Length))
}
tbRead.Text = readSB.ToString()
}
}catch (Exception ex)
{
MessageBox.Show(ex.Message)
}
}
有个小遗憾就是,如果NFC Reader没有连接的时候启动app会抛出异常,而如果app已经启动再拔出然后插入NFC Reader又会无法再读卡除非重启app或者重新初始化。这个需要有点改进。
2,解析
根老岁据上述步骤,我们得到了某张卡的信息如下:
04 C9 02 47 0A C9 5A 84 1D 48 00 00 E1 10 12 00 0A C9 5A 84 1D 48 00 00 E1 10 12 00 01 03 A0 0C
1D 48 00 00 E1 10 12 00 01 03 A0 0C 34 03 0F D1
E1 10 12 00 01 03 A0 0C 34 03 0F D1 01 0B 54 02 01 03 A0 0C 34 03 0F D1 01 0B 54 02 65 6E 32 30 34 03 0F D1 01 0B 54 02 65 6E 32 30 31 38 31 30 01 0B 54 02 65 6E 32 30 31 38 31 30 32 35 FE 00 65 6E 32 30 31 38 31 30 32 35 FE 00 00 00 00 00 31 38 31 30 32 35 FE 00 00 00 00 00 00 00 00 00 32 35 FE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
(以下省略...)
然后,我们对它做一点移位:
04 C9 02 47 0A C9 5A 84 1D 48 00 00 E1 10 12 00 伏闭0A C9 5A 84 1D 48 00 00 E1 10 12 00 01 03 A0 0C
1D 48 00 00 E1 10 12 00 01 03 A0 0C 34 03 0F D1
E1 10 12 00 01 03 A0 0C 34 03 0F D1 01 0B 54 02
01 03 A0 0C 34 03 0F D1 01 0B 54 02 65 6E 32 30
34 03 0F D1 01 0B 54 02 65 6E 32 30 31 38 31 30
01 0B 54 02 65 6E 32 30 31 38 31 30 32 35 FE 00
65 6E 32 30 31 38 31 30 32 35 FE 00 00 00 00 00
31 38 31 30 32 35 FE 00 00 00 00 00 00 00 00 00
32 35 FE 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
可以看出,每一行只有第一列是我们需要的tag信息。
04 C9 02 470A C9 5A 841D 48 00 00E1 10 12 00
01 03 A0 0C
34 03 0F D101 0B 54 0265 6E 32 3031 38 31 3032 35 FE 00
前面的四行是卡的UID以及制造商等信息。我们只需要关心下半段的数据。
01 (Tag: Lock Control TLV)03 (Length: 3 bytes)
A0 0C 34 (Value: Information on position and function of lock bytes)03 (Tag: NDEF Message TLV)
0F (Length: 15 bytes)
D1 01 0B 54 02 65 6E 32 30 31 38 31 30 32 35 FE (Tag: Terminator TLVhas no length field)00
所以,我们得到了NDEF message:D1 01 0B 54 02 65 6E 32 30 31 38 31 30 32 35
NDEF message:
D1 (Header byte of record 1)01 (Type length: 1 byte)
0B (Payload length: 11 bytes)54 (Type: "T")02 65 6E 32 30 31 38 31 30 32 35 (Payload field)
我们再分析最为关键的payload field,如下:
The payload field:02 (Status byte: Text is UTF-8 encoded, Language code has a length of 2 bytes)65 6E (Language code: "en")32 30 31 38 31 30 32 35 (Text: "20181025")
可以用在线工具来验证一下 “32 30 31 38 31 30 32 35 ”
最后,上述步骤,用写C#的实现如下(不保证所有Mifare卡适用):
private string GetNfcTag(List<byte[]>cardContentList)
{
List<byte>cardBytes = new List<byte>() foreach(byte[] rowCardContent in cardContentList)
{
cardBytes.AddRange(rowCardContent.Take(4))
} byte[] cardUid = cardBytes.Take(8).ToArray() string cardUidStr = Utility.ByteToHex(cardUid, 0, cardUid.Length) byte[] cardMaker = cardBytes.Skip(8).Take(8).ToArray() string cardMakerStr = Utility.ByteToHex(cardMaker, 0, cardMaker.Length) byte[] memoryBytes = cardBytes.Skip(16).ToArray() byte lockControlByte = memoryBytes[0] byte lockByteCount = memoryBytes[1]//how many bytes are the lock bytes
byte[] lockBytes = memoryBytes.Skip(2).Take(lockByteCount).ToArray() int nedfLengthByteIndex = 1 + lockByteCount + 1 + 1 byte ndefLength = memoryBytes[nedfLengthByteIndex] if (ndefLength == 0)//Tag empty
return string.Empty byte[] ndefBytes = memoryBytes.Skip(nedfLengthByteIndex + 1).Take(ndefLength).ToArray() byte payloadHeader = ndefBytes[0] byte payloadTypeLength = ndefBytes[1] byte payloadLength = ndefBytes[2] byte[] payloadType = ndefBytes.Skip(3).Take(payloadTypeLength).ToArray() byte[] payloadBytes = ndefBytes.Skip(3 + payloadType.Length).Take(payloadLength).ToArray() byte languageCodeLength = payloadBytes[0] byte[] languageCode = payloadBytes.Skip(1).Take(languageCodeLength).ToArray() byte[] tag = payloadBytes.Skip(1 + languageCode.Length).Take(payloadLength - languageCode.Length - 1).ToArray() string tagHex= Utility.ByteToHex(tag , 0, tag .Length) string tagStr = Encoding.UTF8.GetString(tag) return tagStr
}
如果你要读取的文件内容不是很多,可以使用 File.ReadAllText(FilePath) 或指定编码方式 File.ReadAllText(FilePath, Encoding)的方法。它们都一次将文本内容全部读完,并返回一个包含全部文本内容的旦纯誉字符串
string str = File.ReadAllText(@"c:\temp\ascii.txt")
// 也可以指定编码方式
string str2 = File.ReadAllText(@"c:\temp\ascii.txt", Encoding.ASCII)
也可以使用方法File.ReadAllLines。该方法返回模段一个字符串数组。每一裤喊行都是一个数组元素。
string[] strs = File.ReadAllLines(@"c:\temp\ascii.txt")
// 也可以指定编码方式
string[] strs2 = File.ReadAllLines(@"c:\temp\ascii.txt", Encoding.ASCII)
当文本的内容比较大时,我们就不要将文本内容一次读完,而应该采用流(Stream)的方式来读取内容。.Net为我们封装了StreamReader类。初始化StreamReader类有很多种方式。下面我罗列出几种
StreamReader sr1 = new StreamReader(@"c:\temp\utf-8.txt")
// 同样也可以指定编码方式
StreamReader sr2 = new StreamReader(@"c:\temp\utf-8.txt", Encoding.UTF8)
FileStream fs = new FileStream(@"C:\temp\utf-8.txt", FileMode.Open, FileAccess.Read, FileShare.None)
StreamReader sr3 = new StreamReader(fs)
StreamReader sr4 = new StreamReader(fs, Encoding.UTF8)
FileInfo myFile = new FileInfo(@"C:\temp\utf-8.txt")
// OpenText 创建一个UTF-8 编码的StreamReader对象
StreamReader sr5 = myFile.OpenText()
// OpenText 创建一个UTF-8 编码的StreamReader对象
StreamReader sr6 = File.OpenText(@"C:\temp\utf-8.txt")
初始化完成之后,你可以每次读一行,也可以每次读一个字符 ,还可以每次读几个字符,甚至也可以一次将所有内容读完。
// 读一行
string nextLine = sr.ReadLine()
// 读一个字符
int nextChar = sr.Read()
// 读100个字符
int nChars = 100
char[] charArray = new char[nChars]
int nCharsRead = sr.Read(charArray, 0, nChars)
// 全部读完
string restOfStream = sr.ReadToEnd()
使用完StreamReader之后,不要忘记关闭它: sr.Closee()
假如我们需要一行一行的读,将整个文本文件读完,下面看一个完整的例子:
StreamReader sr = File.OpenText(@"C:\temp\ascii.txt")
string nextLine
while ((nextLine = sr.ReadLine()) != null)
{
如果用【现成的读卡器】:查梁顷消询读卡器自带的【函数库】,注意要和你的 IC 型号匹配。
如果【自己做读卡器】:
这个难度就大了。
查询 IC 卡的技术文档,研究 IC 卡读取是的【时序电路】,用芯乎贺片(如51单片机)时序这
种时序,即可读写 IC 卡。
至于你图片上的那个界面,应该是用 VB 开发出来的。如果你用【现成的读卡器】,那么橡知读写 IC一般会有 VB 的函数可以调用的,实现起来会比较容易。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)