2010-01-09 43 views
7

Quiero generar un archivo .torrent en Java, pero no quiero una gran API que haga algo como raspar rastreadores, siembra, etc. Esto es solo para un cliente que genera metadatos. ¿Qué soluciones ligeras existen? Solo estoy generando un .torrent de un solo archivo .zip.¿Cómo puedo generar un .torrent en Java?

Gracias!

Respuesta

22

He creado esta pieza autónoma de código Java para preparar un archivo .torrent con un único archivo.

El archivo .torrent se crea llamando al createTorrent() pasando el nombre del archivo .torrent, el nombre del archivo compartido y la URL del rastreador.

createTorrent() utiliza hashPieces() para discutir a fondo el archivo piezas utilizando la clase de Java MessageDigest. A continuación, createTorrent() prepara un diccionario de información meta que contiene los metadatos de torrente. Este diccionario se serializa en el formato de bencode utilizando los métodos encode*() y se guarda en un archivo .torrent.

Consulte el BitTorrent spec para obtener más información.

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"); 
    } 
} 

Código edita: hacer esto un poco más compacto, fijar métodos visibilidad, utilice caracteres literales en su caso, utilizar instanceof Number. Y más recientemente, , lea el archivo usando E/S de bloque porque estoy tratando de usarlo para E/S real y byte es simplemente lento,

10

Comenzaría con Java Bittorrent API. La jarra tiene unos 70 Kb pero probablemente puedas quitarla eliminando las clases que no son necesarias para crear torrentes. El SDK tiene un ejemplo ExampleCreateTorrent.java que ilustra cómo hacer exactamente lo que necesita.

También puede ver cómo se implementa en los clientes de Java de código abierto como Azureus.

Cuestiones relacionadas