Skip to content

Commit e4ddf1b

Browse files
committed
Rename getInfoHash to calculateInfoHash in InfoHashCalculator, update README and examples
1 parent f379de1 commit e4ddf1b

7 files changed

Lines changed: 127 additions & 47 deletions

File tree

README.md

Lines changed: 112 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,114 @@
11
# Java Torrent File Parser
2-
A simple Java library that allows you to read the contents of a `.torrent` file.
3-
4-
# Features
5-
- Parse a .torrent file into a TorrentMetadata object
6-
- Parse a .torrent file into a Map<String, Object>
7-
- Get the info hash
8-
- Supports single-file and multi-file torrents
9-
- Access optional metadata fields such as trackers, comments, and creator info
10-
11-
### TorrentMetadata object structure
12-
public class TorrentMetadata {
13-
Map<String, Object> otherValues;
14-
String announce;
15-
Long totalLength;
16-
List<TorrentFile> files;
17-
String name;
18-
Long pieceLength;
19-
String pieces;
20-
boolean isSingleFile;
21-
boolean isPrivate;
22-
String infoHash; // null if computeInfoHash is set to false
2+
A simple Java library for parsing and encoding `.torrent` files using the Bencode format.
3+
4+
## Requirements
5+
- Java 17 or higher
6+
- Maven (for building locally)
7+
8+
## Installation
9+
10+
Because this library is not currently published to Maven Central, you will need to install it to your local Maven repository first.
11+
12+
```bash
13+
git clone https://github.com/robothaver/JavaTorrentFileParser
14+
cd JavaTorrentFileParser
15+
mvn clean install
16+
```
17+
18+
**Maven:**
19+
```xml
20+
<dependency>
21+
<groupId>com.robothaver</groupId>
22+
<artifactId>TorrentFileParser</artifactId>
23+
<version>1.2</version>
24+
</dependency>
25+
```
26+
27+
## Features
28+
29+
### Parsing
30+
31+
- Parse `.torrent` files into a `TorrentMetadata` object
32+
- Parse `.torrent` files into a `Map<String, Object>`
33+
- Calculate the info hash
34+
- Support for both single-file and multi-file torrents
35+
- Access optional metadata fields (trackers, comments, creator info, Azureus properties and more)
36+
- Reusable and thread-safe parser
37+
38+
### Encoding
39+
40+
- Encode a `Map<String, Object>` into a Bencoded byte array
41+
- Encode a `TorrentMetadata` object into a Bencoded byte array
42+
- Reusable and thread-safe encoder
43+
44+
## Raw byte and string handling
45+
- If you parse into a `TorrentMetadata` object, the parser automatically converts known text fields into Java Strings. However, any unrecognized fields placed into the `otherValues` map will remain as raw byte arrays and must be converted manually.
46+
- If you parse directly to a `Map<String, Object>`, all string values will remain as byte arrays and require manual conversion.
47+
48+
## Usage
49+
### Parser usage
50+
```java
51+
public static void main(String[] args) throws IOException, MalformedTorrentFileException, NoSuchAlgorithmException {
52+
Path path = Path.of("Path to torrent file");
53+
byte[] bytes = Files.readAllBytes(path);
54+
Instant start = Instant.now();
55+
56+
TorrentFileParser torrentParser = new TorrentFileParserImpl();
57+
58+
// Parse to metadata object
59+
// If InfoHashCalculator is provided the info hash will get calculated
60+
TorrentMetadata torrentMetadata = torrentParser.parseToMetadata(bytes, new InfoHashCalculatorImpl());
61+
// Or use torrentParser.parseToMap() to parse to a map
2362

24-
// Optional fields
25-
List<List<String>> announceList;
26-
String creator;
27-
Long creationDate;
28-
String source;
29-
String comment;
30-
String encoding;
31-
Map<String, Object> azureusProperties;
32-
}
63+
Instant finish = Instant.now();
64+
65+
System.out.println(torrentMetadata.getName());
66+
long timeElapsed = Duration.between(start, finish).toMillis();
67+
System.out.println("Parsing finished in " + timeElapsed + "ms");
68+
}
69+
```
70+
71+
*Note: If you parse to a map and provide an `InfoHashCalculator`, the calculated info hash will get added to the root of the returned map.*
72+
73+
### Encoder usage
74+
```java
75+
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, MalformedTorrentFileException {
76+
Path path = Path.of("Path to torrent file");
77+
TorrentFileParserImpl torrentFileParser = new TorrentFileParserImpl();
78+
byte[] fileBytes = Files.readAllBytes(path);
79+
80+
// Encode a map to bencoded byte array (reencode a .torrent file in this example)
81+
Map<String, Object> torrentMap = torrentFileParser.parseToMap(fileBytes, null);
82+
TorrentEncoderImpl torrentEncoder = new TorrentEncoderImpl();
83+
byte[] bytes = torrentEncoder.encodeTorrentMap(torrentMap);
84+
85+
// Encode metadata object to bencoded byte array
86+
TorrentMetadata torrentMetadata = torrentFileParser.parseToMetadata(fileBytes, null);
87+
byte[] metadataBytes = torrentEncoder.encodeTorrentMetadata(torrentMetadata);
88+
}
89+
```
90+
91+
## TorrentMetadata object structure
92+
```java
93+
public class TorrentMetadata {
94+
private final Map<String, Object> otherValues;
95+
private String announce;
96+
private String name;
97+
private Long pieceLength;
98+
private boolean isSingleFile;
99+
private boolean isPrivate;
100+
private Long totalLength;
101+
private byte[] pieces;
102+
private final List<TorrentFile> files;
103+
String infoHash; // null if no InfoHashCalculator is provided
104+
105+
// Optional fields
106+
private List<List<String>> announceList;
107+
private String creator;
108+
private Long creationDate;
109+
private String source;
110+
private String comment;
111+
private String encoding;
112+
private Map<String, Object> azureusProperties;
113+
}
114+
```

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.robothaver</groupId>
88
<artifactId>TorrentFileParser</artifactId>
9-
<version>1.1.7</version>
9+
<version>1.2</version>
1010

1111
<properties>
1212
<maven.compiler.source>17</maven.compiler.source>

src/main/java/com/robothaver/torrentfileparser/Encode.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,28 @@
22

33
import com.robothaver.torrentfileparser.domain.TorrentMetadata;
44
import com.robothaver.torrentfileparser.encoder.TorrentEncoderImpl;
5-
import com.robothaver.torrentfileparser.encoder.types.*;
65
import com.robothaver.torrentfileparser.exception.MalformedTorrentFileException;
7-
import com.robothaver.torrentfileparser.parser.InfoHashCalculatorImpl;
86
import com.robothaver.torrentfileparser.parser.TorrentFileParserImpl;
97

108
import java.io.IOException;
119
import java.nio.file.Files;
1210
import java.nio.file.Path;
1311
import java.security.NoSuchAlgorithmException;
14-
import java.util.Arrays;
1512
import java.util.Map;
1613

1714
public class Encode {
1815
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, MalformedTorrentFileException {
19-
Path path = Path.of("[nCore][game_iso]Forza.Horizon.6-RUNE.torrent");
16+
Path path = Path.of("Path to torrent file");
2017
TorrentFileParserImpl torrentFileParser = new TorrentFileParserImpl();
2118
byte[] fileBytes = Files.readAllBytes(path);
19+
20+
// Encode a map to bencoded byte array
2221
Map<String, Object> torrentMap = torrentFileParser.parseToMap(fileBytes, null);
23-
TorrentMetadata torrentMetadata = torrentFileParser.parseToMetadata(fileBytes, null);
2422
TorrentEncoderImpl torrentEncoder = new TorrentEncoderImpl();
25-
2623
byte[] bytes = torrentEncoder.encodeTorrentMap(torrentMap);
27-
byte[] metadataBytes = torrentEncoder.encodeTorrentMetadata(torrentMetadata);
2824

29-
System.out.println("Encoded map byte length: " + bytes.length);
30-
System.out.println("Metadata byte length: " + metadataBytes.length);
31-
System.out.println("Torrent file byte length: " + fileBytes.length);
32-
System.out.println("Bytes equal: " + Arrays.equals(bytes, fileBytes));
33-
Files.write(Path.of("encoded.torrent"), bytes);
34-
Files.write(Path.of("metadata.torrent"), metadataBytes);
25+
// Encode metadata object to bencoded byte array
26+
TorrentMetadata torrentMetadata = torrentFileParser.parseToMetadata(fileBytes, null);
27+
byte[] metadataBytes = torrentEncoder.encodeTorrentMetadata(torrentMetadata);
3528
}
3629
}

src/main/java/com/robothaver/torrentfileparser/Main.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ public static void main(String[] args) throws IOException, MalformedTorrentFileE
2020
Instant start = Instant.now();
2121

2222
TorrentFileParser torrentParser = new TorrentFileParserImpl();
23+
24+
// Parse to metadata object
25+
// If InfoHashCalculator is provided the info hash will get calculated
2326
TorrentMetadata torrentMetadata = torrentParser.parseToMetadata(bytes, new InfoHashCalculatorImpl());
27+
// Or use torrentParser.parseToMap() to parse to a map
28+
2429
Instant finish = Instant.now();
2530

2631
System.out.println(torrentMetadata.getName());
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package com.robothaver.torrentfileparser.parser;
22

33
public interface InfoHashCalculator {
4-
String getInfoHash(byte[] infoBytes);
4+
String calculateInfoHash(byte[] infoBytes);
55
}

src/main/java/com/robothaver/torrentfileparser/parser/InfoHashCalculatorImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public InfoHashCalculatorImpl() throws NoSuchAlgorithmException {
1212
}
1313

1414
@Override
15-
public String getInfoHash(byte[] infoBytes) {
15+
public String calculateInfoHash(byte[] infoBytes) {
1616
return HexFormat.of().formatHex(messageDigest.digest(infoBytes));
1717
}
1818
}

src/main/java/com/robothaver/torrentfileparser/parser/ParseWorker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private void tryCalculateInfoHash(Map<String, Object> map) {
127127
if (infoHashCalculator == null) return;
128128

129129
byte[] infoDictionaryBytes = Arrays.copyOfRange(bytes, infoDictStartIndex, iterator);
130-
String infoHash = infoHashCalculator.getInfoHash(infoDictionaryBytes);
130+
String infoHash = infoHashCalculator.calculateInfoHash(infoDictionaryBytes);
131131
if (torrentBuilder != null) torrentBuilder.setInfoHash(infoHash); else map.put("infoHash", infoHash);
132132
}
133133

0 commit comments

Comments
 (0)