代码之家  ›  专栏  ›  技术社区  ›  Kristopher Ives

如何在Java中生成一个?

  •  7
  • Kristopher Ives  · 技术社区  · 15 年前

    我想在Java中生成一个.rOrm文件,但我不需要一个大的API来做任何事情,比如删除跟踪器、播种等等。这只适用于生成元数据的客户端。存在哪些轻量级解决方案?我只生成一个.zip文件的.torrent。

    谢谢!

    2 回复  |  直到 13 年前
        1
  •  22
  •   huaiyuan    13 年前

    我把这个自包含的Java代码放在一起,用一个文件编写一个.Trand文件。

    .torrent文件是通过调用 createTorrent() 传递.torrent文件的名称、共享文件的名称和跟踪器URL。

    创建() 使用 hashPieces() 散列文件 使用Java的 MessageDigest 班级。然后 创建() 准备一个 元信息字典 包含Torrent元数据。然后在适当的 本代码 使用格式化 encode*() 方法并保存在.torrent文件中。

    BitTorrent spec 详情。

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

    代码编辑: 使其更加紧凑,修复方法的可见性,在适当的地方使用字符文本,使用 instanceof Number .而且最近 使用块I/O读取文件 因为我正试图将其用于实际,而字节I/O速度很慢,

        2
  •  10
  •   Alex Jasmin    13 年前

    我从开始 Java Bittorrent API .jar大约是70kb,但您可以通过删除创建Torrent不需要的类来将其剥离。SDK有一个示例 ExampleCreateTorrent.java 演示如何准确地执行您需要的操作。

    您还可以看看它是如何在开源Java客户端中实现的,比如AZURUS。