Advertisement
xnim

Bencode to XML

Jul 17th, 2012
595
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.02 KB | None | 0 0
  1. //File 1
  2.  
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.IO;
  8. using System.Xml;
  9.  
  10. namespace TorrentFile
  11. {
  12. #region BDictionary
  13.  
  14.     /// <summary>
  15.     /// Dictionary
  16.     /// start - 'd'
  17.     /// end - 'e'
  18.     /// Example - d2:hi7:goodbyee => ("hi" => "goodbye")
  19.     /// </summary>
  20.     public class BDictionary
  21.     {
  22.         protected List<BElement> FirstItem = null;
  23.         protected List<BElement> SecondItem = null;
  24.  
  25.         public BDictionary()
  26.         {
  27.             FirstItem = new List<BElement>();
  28.             SecondItem = new List<BElement>();
  29.         }
  30.  
  31.         public int Count{
  32.             get
  33.             {
  34.                 return FirstItem.Count;
  35.             }
  36.         }
  37.         /// <summary>
  38.         /// index
  39.         /// </summary>
  40.         /// <param name="index"></param>
  41.         /// <returns></returns>
  42.         public BElement[] this[int index]
  43.         {
  44.         get{
  45.                 if (FirstItem.Count > index)
  46.                 {
  47.                 BElement[] Items = new BElement[2];
  48.                 Items[0] = FirstItem[index];
  49.                 Items[1] = SecondItem[index];
  50.                 return Items;
  51.                 }
  52.                 return new BElement[2];
  53.             }
  54.         set{
  55.             if (FirstItem.Count > index)
  56.                 {
  57.                     FirstItem[index] = value[0];
  58.                     SecondItem[index] = value[1];
  59.                 }
  60.             else
  61.                 {
  62.                     FirstItem.Add(value[0]);
  63.                     SecondItem.Add(value[1]);
  64.                 }
  65.             }
  66.         }
  67.         /// <summary>
  68.         /// Adds new item to dictionary
  69.         /// </summary>
  70.         /// <param name="First">First Item</param>
  71.         /// <param name="Second">Second Item</param>
  72.         public void Add(BElement First, BElement Second)
  73.         {
  74.             FirstItem.Add(First);
  75.             SecondItem.Add(Second);
  76.         }
  77.     }
  78. #endregion
  79.     #region BList
  80.     /// <summary>
  81.     /// List
  82.     /// start - 'l'
  83.     /// end - 'e'
  84.     /// Example - l5:helloi145e => ("hello",145)
  85.     /// </summary>
  86.     public class BList
  87.     {
  88.         List<BElement> Items = null;
  89.  
  90.         public BList()
  91.         {
  92.             Items = new List<BElement>();
  93.         }
  94.  
  95.         public BElement this[int index]
  96.         {
  97.             get
  98.             {
  99.                 if (Items.Count > index)
  100.                 {
  101.                    
  102.                     return Items[index];
  103.                 }
  104.                 return new BElement();
  105.             }
  106.             set
  107.             {
  108.                 if (Items.Count > index)
  109.                 {
  110.                     Items[index] = value;
  111.                 }
  112.                 else
  113.                 {
  114.                     Items.Add(value);
  115.                 }
  116.             }
  117.         }
  118.        public int Count
  119.         {
  120.             get
  121.             {
  122.                 return Items.Count;
  123.             }
  124.         }
  125.  
  126.         /// <summary>
  127.         /// Adds new item to dictionary
  128.         /// </summary>
  129.         /// <param name="First">First Item</param>
  130.         /// <param name="Second">Second Item</param>
  131.         public void Add(BElement inf)
  132.         {
  133.             Items.Add(inf);
  134.         }
  135.     }
  136. #endregion
  137.     #region BItem
  138.     /// <summary>
  139.     /// integer value
  140.     /// start - 'i'
  141.     /// end - 'e'
  142.     /// Example - i145e => 145
  143.     /// string value
  144.     /// start - length
  145.     /// end -
  146.     /// Example 5:hello => "hello"
  147.     /// </summary>
  148.      public class BItem
  149.     {
  150.         protected string strValue = "";
  151.         protected int intValue = 0;
  152.         protected bool IsInt = true;
  153.          public bool isInt
  154.         {
  155.             get
  156.             {
  157.                 return IsInt;
  158.             }
  159.         }
  160.         public BItem(string A)
  161.         {
  162.             strValue = A;
  163.             IsInt = false;
  164.         }
  165.         public BItem(int A)
  166.         {
  167.             IsInt = true;
  168.             intValue = A;
  169.         }
  170.         public string ToString()
  171.         {
  172.             if (IsInt)
  173.                 return intValue.ToString();
  174.             return strValue;
  175.         }
  176.     }
  177. #endregion
  178. #region BElement
  179.      /// <summary>
  180.     /// Universal bencode store
  181.     /// </summary>
  182.     public class BElement
  183.     {
  184.        public BItem STDItem = null;
  185.        public BList LSTItem = null;
  186.        public BDictionary DICItem = null;
  187.         /// <summary>
  188.         /// Создание и чтение простого типа данных string\integer
  189.         /// </summary>
  190.         /// <param name="Reader">поток чтения</param>
  191.         /// <param name="CurrentCode">Считанный заранее символ</param>
  192.         public void AddToBItem(StreamReader Reader, char CurrentCode)
  193.         {
  194.             char C;
  195.             if (CurrentCode == 'i')
  196.             {//считывание числа
  197.                 string Value= "";
  198.                 C = (char)Reader.Read();
  199.                 while (C != 'e')
  200.                 {//конец
  201.                     Value += C;
  202.                     C = (char)Reader.Read();
  203.                 }
  204.                 try
  205.                 {
  206.                     int Res = Int32.Parse(Value);
  207.                     STDItem = new BItem(Res);
  208.                 }
  209.                 catch (Exception ex)
  210.                 {
  211.                     //Здесь можно вызвать throw ошибку. А можно сделать объект null'ом
  212.                     STDItem = null;
  213.                 }
  214.                 return;
  215.             }
  216.             int length = (int)CurrentCode - (int)'0';
  217.             C = (char)Reader.Read();
  218.             while (C != ':' && (C>='0' && C<='9'))
  219.             {
  220.                 length = length * 10 + (int)C - (int)'0';
  221.                 C = (char)Reader.Read();
  222.             }
  223.             if (C!= ':')
  224.             {//Можно вызвать ошибку (так же как выше, просто обнулим объект, вместо throw new Exception("Неверно задан объект");
  225.                 // так как второй способ throw требует обработки выше по коду... а пока пишем только класс =)
  226.                 STDItem = null;
  227.                 return;
  228.             }
  229.             string value = "";
  230.             for (int CurrentCount = 0; CurrentCount < length; CurrentCount++)
  231.             {
  232.                 value += (char)Reader.Read();
  233.             }
  234.             STDItem = new BItem(value);
  235.  
  236.         }
  237.        /// <summary>
  238.        /// список. Считаем, что l была считана
  239.        /// </summary>
  240.        /// <param name="Reader">ридер файла</param>
  241.         public void AddToBList(StreamReader Reader)
  242.         {
  243.             LSTItem = new BList();
  244.             BElement Temp = GetNewBElement(Reader);
  245.             while (Temp != null)
  246.             {
  247.                 LSTItem.Add(Temp);
  248.                 Temp = GetNewBElement(Reader);
  249.             }
  250.             if (LSTItem.Count == 0) LSTItem = null;//опять же - здесь можно генерировать ошибку о неверной структуре файла.
  251.         }
  252.         /// <summary>
  253.         /// Считывание словаря
  254.         /// </summary>
  255.         /// <param name="Reader">поток чтения файла</param>
  256.         public void AddToBDic(StreamReader Reader)
  257.         {
  258.             DICItem = new BDictionary();
  259.             BElement FirstTemp = GetNewBElement(Reader);
  260.             BElement SecondTemp = GetNewBElement(Reader);
  261.             while (FirstTemp != null || SecondTemp != null)
  262.             {
  263.                 DICItem.Add(FirstTemp, SecondTemp);
  264.                 FirstTemp = GetNewBElement(Reader);
  265.                 SecondTemp = GetNewBElement(Reader);
  266.             }
  267.             if (DICItem.Count == 0) DICItem = null;//Либо писать об ошибке в структуре файла
  268.         }
  269.  
  270.         /// <summary>
  271.         /// Определяем тип следующего элемента. Запускаем создание
  272.         /// </summary>
  273.         /// <param name="Reader">поток чтения</param>
  274.         /// <returns>Новый элемент</returns>
  275.         public static BElement GetNewBElement(StreamReader Reader)
  276.         {
  277.             char C = (char)Reader.Read();
  278.             switch (C)
  279.                 {
  280.                     case '0':
  281.                     case '1':
  282.                     case '2':
  283.                     case '3':
  284.                     case '4':
  285.                     case '5':
  286.                     case '6':
  287.                     case '7':
  288.                     case '8':
  289.                     case '9':
  290.                     case 'i':
  291.                         {//простой тип данных
  292.                             BElement STDElement = new BElement();
  293.                             STDElement.AddToBItem(Reader, C);
  294.                             return STDElement;
  295.                         }
  296.                     case 'l':
  297.                         {//список
  298.                             BElement LSTElement = new BElement();
  299.                             LSTElement.AddToBList(Reader);
  300.                             return LSTElement;
  301.                         }
  302.                
  303.                 case 'd':
  304.                         {//словарь
  305.                             BElement DICElement = new BElement();
  306.                             DICElement.AddToBDic(Reader);
  307.                             return DICElement;
  308.                         }
  309.                 default://("e")
  310.                         return null;
  311.                 }
  312.         }
  313.     }
  314. #endregion
  315. #region FileBEncoding
  316.  
  317.    public class FileBEncoding
  318.     {
  319.        List<BElement> BenItems;//Если подразумеваем только один элемент на файл, то пишем BElement BenItem
  320.  
  321.        BElement this[int index]
  322.        {
  323.            get
  324.            {
  325.                if (BenItems.Count > index)
  326.                    return BenItems[index];
  327.                return null;
  328.            }
  329.            set
  330.            {
  331.                if (BenItems.Count > index)
  332.                {
  333.                    BenItems[index] = value;
  334.                }
  335.                else throw new Exception("Выход за пределы. Ничего не записано");
  336.            }
  337.        }
  338.  
  339.        public FileBEncoding(string Path)
  340.        {
  341.            if (!File.Exists(Path)) return;
  342.            BenItems = new List<BElement>();
  343.            StreamReader Reader = new StreamReader(Path, Encoding.ASCII);
  344.            while (!Reader.EndOfStream)
  345.            {
  346.                BElement temp = BElement.GetNewBElement(Reader);
  347.                if (temp != null)
  348.                    BenItems.Add(temp);
  349.            }
  350.            Reader.Close();
  351.        }
  352. #endregion
  353. //////////////////////////////////////////////////////////////////////////////////////////////
  354. #region StringBuild
  355.        
  356.        private string BElementToSTR(BElement CurrentElement, int TabCount, bool Ignore = true)
  357.        {
  358.            //для корректной обработки некорректных файлов
  359.            if (CurrentElement == null) return "";//Так как выше по ходу, при неверное структуре файла не выдавали исключение.
  360.  
  361.            string Result = "";//строка результата
  362.            if (Ignore)//табуляция строки для словаря не нужна
  363.            PasteTab(ref Result, TabCount);
  364.            if (CurrentElement.STDItem != null)
  365.            {
  366.                Result += CurrentElement.STDItem.ToString();
  367.                return Result;
  368.            }
  369.            if (CurrentElement.LSTItem != null)
  370.            {//обработка списка
  371.                Result += "List{\n";
  372.                for (int i = 0; i < CurrentElement.LSTItem.Count; i++)
  373.                    Result += BElementToSTR(CurrentElement.LSTItem[i], TabCount + 1) + '\n';
  374.                PasteTab(ref Result, TabCount);
  375.                Result += "}List\n";
  376.                return Result;
  377.            }
  378.            if (CurrentElement.DICItem != null)
  379.            {//обработка словаря
  380.                Result += "Dict{\n";
  381.                for (int i = 0; i < CurrentElement.DICItem.Count; i++)
  382.                {
  383.                    Result += BElementToSTR(CurrentElement.DICItem[i][0], TabCount + 1) +" => "+ BElementToSTR(CurrentElement.DICItem[i][1], TabCount+1,false) + '\n';
  384.                }
  385.                PasteTab(ref Result, TabCount);
  386.                Result += "}Dict\n";
  387.                return Result;
  388.            }
  389.            return "";//Если все элементы null, то возвратим пустую строку
  390.        }
  391.  
  392.        private string PasteTab(ref string STR,int count)
  393.        {//табуляция
  394.            for (int i = 0; i < count; i++)
  395.                STR += '\t';
  396.             return STR;
  397.        }
  398.  
  399.        public string ToString()
  400.        {
  401.            string Result = "";
  402.            for (int i = 0; i < BenItems.Count; i++)
  403.            {
  404.                Result += BElementToSTR(BenItems[i], 0) + "\n\n";
  405.            }
  406.            return Result;
  407.        }
  408. #endregion
  409. #region XMLBuild
  410.        private void BElementToXML(BElement Current, XmlWriter Writer, int order = 0)
  411.        {
  412.            if (Current == null) return;//корректная обработка некорректных файлов
  413.            if (Current.STDItem != null)
  414.            {//простой элемент запишем как аттрибут
  415.                Writer.WriteAttributeString("STDType"+'_'+order.ToString(), Current.STDItem.ToString());
  416.                return;
  417.            }
  418.            if (Current.LSTItem != null)
  419.            {//список
  420.                Writer.WriteStartElement("List");//данный метод записывает ноду <List>
  421.                for (int i = 0; i < Current.LSTItem.Count; i++)
  422.                    BElementToXML(Current.LSTItem[i],Writer,order);//рекурсивное раскручивание
  423.                Writer.WriteEndElement();//закрываем ноду </List>
  424.                return;
  425.            }
  426.            if (Current.DICItem != null)
  427.            {//словарь (аналогично списку)
  428.                Writer.WriteStartElement("Dictionary");
  429.                for (int i = 0; i < Current.DICItem.Count; i++)
  430.                {
  431.                    Writer.WriteStartElement("Dictionary_Items");
  432.                    BElementToXML(Current.DICItem[i][0], Writer,order);
  433.                    BElementToXML(Current.DICItem[i][1], Writer,order+1);
  434.                    Writer.WriteEndElement();
  435.                }
  436.                Writer.WriteEndElement();
  437.                return;
  438.            }
  439.            return;
  440.        }
  441.        public void ToXMLFile(string path)
  442.        {
  443.            using (XmlTextWriter XMLwr = new XmlTextWriter(path, System.Text.Encoding.Unicode))
  444.            {
  445.                XMLwr.Formatting = Formatting.Indented;
  446.                XMLwr.WriteStartElement("Bencode_to_XML");
  447.                foreach (BElement X in BenItems)
  448.                {
  449.                    XMLwr.WriteStartElement("BenItem");
  450.                    BElementToXML(X, XMLwr);
  451.                    XMLwr.WriteEndElement();
  452.                }
  453.                XMLwr.WriteEndElement();    
  454.            }
  455.        }
  456.  
  457. #endregion
  458.     }
  459. }
  460.  
  461.  
  462. //File 2 (example)
  463.  
  464. using System;
  465. using System.Collections.Generic;
  466. using System.Linq;
  467. using System.Text;
  468. using TorrentFile;
  469. using System.IO;
  470.  
  471. namespace TorrentFile
  472. {
  473.     class Program
  474.     {
  475.         static void Main(string[] args)
  476.         {
  477.             FileBEncoding Change = new FileBEncoding("SomePath.torrent");
  478.             Console.Write(Change.ToString());
  479.             /*using (StreamWriter WriteFile = new StreamWriter("OutputFile.txt"))
  480.             {
  481.                 WriteFile.Write(Change.ToString());
  482.             }*/
  483.             Change.ToXMLFile("SomeOutputFile.xml");
  484.             Console.ReadLine();
  485.         }
  486.     }
  487. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement