我想用Java生成一个.torrent文件,但我不想要一个大的API来做任何事情,比如抓取跟踪器,播种等等。这只适用于生成元数据的客户端。有哪些轻量级解决方案我只生成一个.zip文件的.torrent。
谢谢!
答案 0 :(得分:22)
我把这个自包含的Java代码放在一起,用一个文件准备一个.torrent文件。
.torrent文件是通过调用createTorrent()
传递.torrent文件的名称,共享文件的名称和跟踪器URL来创建的。
createTorrent()
使用hashPieces()
使用Java的MessageDigest
类来散列文件件。然后createTorrent()
准备包含torrent元数据的元信息字典。然后使用encode*()
方法以适当的 bencode 格式对此词典进行序列化,并保存在.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只是很慢,
答案 1 :(得分:10)
我从Java Bittorrent API开始。罐子大约70Kb,但你可以通过删除创建种子所不需要的类来剥离它。 SDK中有一个示例 ExampleCreateTorrent.java ,说明如何完全按照您的需要进行操作。
您还可以了解它是如何在开源Java客户端(如Azureus)中实现的。