李超

cc编程笔记本。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

class MyFile < File
  
def peek(len)
    str 
= self.read(len)
    self.pos 
-= len
    str
  end  
end

#字段信息
class TVal
  attr_accessor :Type
  attr_accessor :Value
  
  
def to_s()
    @Value
  end
  
end

#文件信息
class TFile
  attr_reader :Length
  attr_reader :Path
  attr_reader :Name
  attr_reader :FirstPiece
  attr_reader :PieceLength
  
  
def initialize(size, fullPath, pStart, pLen)
    @Length 
= Size
    @FirstPiece 
= pStart
    @PieceLength 
= pLen
    fileNamePos 
= fullPath.rindex('\\')
    
if fileNamePos.nil? then
      @Path 
= ""
      @Name 
= fullPath
    
else
      @Path 
= fullPath[0..fileNamePos]
      @Name 
= fullPath[fileNamePos..fullPath.length-1]
    end
  end
end
  

class TorrentParser
  attr_accessor :Root
  
def initialize(tPath)
    
    @Path 
= tPath
    @Size 
= nil
    
    @Root 
= nil
    @Files 
= nil
    
    @Torrent 
= nil
    @TotalValues 
= 0
    
    @InfoStart 
= nil
    @InfoEnd 
= nil
    
  end
  
#主函数
  def Process()
    
raise "File doesn't exist"  if !MyFile.exist? @Path #检测文件路径
    @TotalValues = 0
    
    @Torrent 
= MyFile.new @Path
    @Torrent.binmode

    
raise "Torrent File Error" if @Torrent.read(1!= 'd'
    
    @Root 
= ProcessDict()
    @Files 
= GetFiles()
    
  end
  
#读取一个字典
  def ProcessDict()
    tempDict 
= Hash.new

    
while @Torrent.peek(1!= 'e' #向后读一个字符 看看是不是e 如果是e的话 说明dictionary结束了
      key = ProcessString() #读取一个Key Name

      
if key == 'info' then #如果是名字为info的key
        @InfoStart = @Torrent.pos #设置info start的index
      end
      
if key == 'pieces' then #如果是pieces的key 则按照特殊的byte方式读取
        val = TVal.new
        val.Type 
= "BYTE"
        val.Value 
= ProcessByte()
        tempDict[key] 
= val
      
else
        val 
= ProcessVal() #否则读该key的Val
        tempDict[key] = val
      end
      
if key == "info" then
        @InfoEnd 
= @Torrent.pos - @InfoStart
      end
    end
    @Torrent.read 
1 #读掉结尾的"e"
    
    
return tempDict
  end
  
  

  
#读取一个字串
  def ProcessString()
    tempLen 
= ''
    tempLen 
+= @Torrent.read(1while @Torrent.peek(1!= ':' #获取字串长度
    
    @Torrent.read(
1# 将后面的冒号读掉    

    content 
= @Torrent.read(tempLen.to_i) #然后读指定长度的字符串 并返回 

    
return content
  end
    

  
#读取字节串
  def ProcessByte()
    tempLen 
= ''
    tempLen 
+= @Torrent.read(1while @Torrent.peek(1!= ':' #获取字串长度
    
    @Torrent.read(
1# 将后面的冒号读掉    
    
    chrs 
= Array.new
    (
1..tempLen.to_i).each{|idx|
      byte 
= @Torrent.readchar
      chrs 
<< "%02X" % byte
    }
    chrs
  end
  

  
#读一个数字
  def ProcessInt()
    tempInt 
= ''
    tempInt 
+= @Torrent.read(1while @Torrent.peek(1!= 'e'

    @Torrent.read(
1#把最后的e读掉
    tempInt.to_i
  end
  
#读一个列表
  def ProcessList()
    tempList 
= Array.new
    
while @Torrent.peek(1!= 'e'
      tempList 
<< ProcessVal
    end
    tempList
  end
    
  
#读取一个Val
  def ProcessVal()
    @TotalValues 
+= 1
    
    val 
= TVal.new
    
    
    case @Torrent.peek(
1)
      when 
'd'
        @Torrent.read(
1)  #把d读掉
        val.Type = "DICT"
        val.Value 
= ProcessDict()
      when 
'l'
        @Torrent.read(
1#把l读掉
        val.Type = "LIST" 
        val.Value 
= ProcessList()
      when 
'i'
        @Torrent.read(
1#把i读掉
        val.Type = "INT"
        val.Value 
= ProcessInt()
      
else
        val.Type 
= "STRING"
        val.Value 
= ProcessString()
    end
    val
  end
  
end

begin
  _torrent 
= TorrentParser.new ARGV.shift
  _torrent.Process
  
  _torrent.Root.map{
|key,value|
    case value.Type
      when 
'LIST'
        puts 
"#{key}(#{value.Type})\t\t#{value.Value}"
      when 
'BYTE'
        puts 
"#{key}(#{value.Type})\t\t%0X", value.Value
      when 
'DICT'
        value.Value.map{
|skey,svalue|
          puts 
"--#{skey}(#{svalue.Type})\t\t#{svalue.Value}"
        }
      
else
        puts 
"#{key}(#{value.Type})\t\t#{value.Value}"
    end
  }
  
rescue
  puts $!
  puts $@
end
posted on 2008-04-08 18:17  coderlee  阅读(1201)  评论(0编辑  收藏  举报