2010-01-09 6 views
7

Ich möchte eine .torrent-Datei in Java generieren, aber ich möchte nicht eine große API, die Scraping Tracker, Seeding usw. tut. Dies ist nur für einen Client, der Metadaten generiert. Welche leichten Lösungen gibt es? Ich erstelle nur ein .torrent einer einzelnen ZIP-Datei.Wie kann ich ein .torrent in Java generieren?

Danke!

Antwort

22

Ich habe diesen eigenständigen Teil von Java-Code zusammengestellt, um eine .torrent-Datei mit einer einzigen Datei vorzubereiten.

Die .torrent-Datei wird erstellt, indem der Name der .torrent-Datei, der Name der freigegebenen Datei und die Tracker-URL mit übergeben werden.

createTorrent() verwendet hashPieces() die Datei Stücke mit Java MessageDigest Klasse Hash. Dann createTorrent() bereitet ein Meta-Info-Wörterbuch mit den Torrent-Metadaten. Dieses Wörterbuch wird dann in dem richtigen Format Bencode unter Verwendung der encode*()-Methoden serialisiert und in einer .torrent-Datei gespeichert.

Siehe die BitTorrent spec für Details.

public class Torrent { 
    private static void encodeObject(Object o, OutputStream out) throws IOException { 
     if (o instanceof String) 
      encodeString((String)o, out); 
     else if (o instanceof Map) 
      encodeMap((Map)o, out); 
     else if (o instanceof byte[]) 
      encodeBytes((byte[])o, out); 
     else if (o instanceof Number) 
      encodeLong(((Number) o).longValue(), out); 
     else 
      throw new Error("Unencodable type"); 
    } 
    private static void encodeLong(long value, OutputStream out) throws IOException { 
     out.write('i'); 
     out.write(Long.toString(value).getBytes("US-ASCII")); 
     out.write('e'); 
    } 
    private static void encodeBytes(byte[] bytes, OutputStream out) throws IOException { 
     out.write(Integer.toString(bytes.length).getBytes("US-ASCII")); 
     out.write(':'); 
     out.write(bytes); 
    } 
    private static void encodeString(String str, OutputStream out) throws IOException { 
     encodeBytes(str.getBytes("UTF-8"), out); 
    } 
    private static void encodeMap(Map<String,Object> map, OutputStream out) throws IOException{ 
     // Sort the map. A generic encoder should sort by key bytes 
     SortedMap<String,Object> sortedMap = new TreeMap<String, Object>(map); 
     out.write('d'); 
     for (Entry<String, Object> e : sortedMap.entrySet()) { 
      encodeString(e.getKey(), out); 
      encodeObject(e.getValue(), out); 
     } 
     out.write('e'); 
    } 
    private static byte[] hashPieces(File file, int pieceLength) throws IOException { 
     MessageDigest sha1; 
     try { 
      sha1 = MessageDigest.getInstance("SHA"); 
     } catch (NoSuchAlgorithmException e) { 
      throw new Error("SHA1 not supported"); 
     } 
     InputStream in = new FileInputStream(file); 
     ByteArrayOutputStream pieces = new ByteArrayOutputStream(); 
     byte[] bytes = new byte[pieceLength]; 
     int pieceByteCount = 0, readCount = in.read(bytes, 0, pieceLength); 
     while (readCount != -1) { 
      pieceByteCount += readCount; 
      sha1.update(bytes, 0, readCount); 
      if (pieceByteCount == pieceLength) { 
       pieceByteCount = 0; 
       pieces.write(sha1.digest()); 
      } 
      readCount = in.read(bytes, 0, pieceLength-pieceByteCount); 
     } 
     in.close(); 
     if (pieceByteCount > 0) 
      pieces.write(sha1.digest()); 
     return pieces.toByteArray(); 
    } 
    public static void createTorrent(File file, File sharedFile, String announceURL) throws IOException { 
     final int pieceLength = 512*1024; 
     Map<String,Object> info = new HashMap<String,Object>(); 
     info.put("name", sharedFile.getName()); 
     info.put("length", sharedFile.length()); 
     info.put("piece length", pieceLength); 
     info.put("pieces", hashPieces(sharedFile, pieceLength)); 
     Map<String,Object> metainfo = new HashMap<String,Object>(); 
     metainfo.put("announce", announceURL); 
     metainfo.put("info", info); 
     OutputStream out = new FileOutputStream(file); 
     encodeMap(metainfo, out); 
     out.close(); 
    } 

    public static void main(String[] args) throws Exception { 
     createTorrent(new File("C:/x.torrent"), new File("C:/file"), "http://example.com/announce"); 
    } 
} 

-Code bearbeitet: Machen Sie dieses ein wenig kompakter, beheben Methoden Sichtbarkeit, verwenden Zeichenliterale geeignet, wenn, instanceof Number verwenden. Und vor kurzem lesen Sie die Datei mit Block E/A, weil ich versuche, es für real zu verwenden und Byte-I/O ist nur langsam,

10

Ich würde mit Java Bittorrent API beginnen. Das jar ist ungefähr 70Kb groß, aber Sie können es wahrscheinlich entfernen, indem Sie die Klassen entfernen, die nicht notwendig sind, um Torrents zu erstellen. Das SDK enthält ein Beispiel ExampleCreateTorrent.java, das veranschaulicht, wie Sie genau das tun, was Sie benötigen.

Sie können auch sehen, wie es in den Open-Source-Java-Clients wie Azureus implementiert ist.

Verwandte Themen