Hi
In Oct. 2025 I posted “NETWORK programming” and showed you how to build yourself some useful apps to ease up your life.
Today, as a Xmas & New Year present, I give you an App that I called “XFileTranfer”. This app allows you to transfer files or the entire of a directory (incl. subdirectories) locally (LAN) or globally (WAN or Internet). The transfer-rate (incl. net latency) is fairly good: 1…4 MB per second (depending on network load and the directory structure -many large or small files). This discrepancy is due to the nature of the handshake (or synchronization) between peer-to-peer communication and file creation on the receiving peer. Fewer files mean less file creation and less synchronization. The internet (web) is based on TCP/IP, which means that the maximum size of a data packet is 64 KB (or 65536 bytes). A higher transmission rate is not possible if you try to send a packet larger than 64 KB, as it is split into multiple packets (of 64 KB each) and then transmitted across the network. However, a higher physical transmission rate (e.g., through fiber optics) can noticeably improve the transmission rate.
XFileTransfer is written in Java Swing and JavaFX (or JFX). However, JavaFX is no longer part of Java as of JDK 11, but is open source, which can lead to problems and bugs due to version conflicts, while Swing remains part of the JDK. Swing’s biggest advantage is its integration into modern Java versions for backward compatibility, but it is currently in maintenance mode. JavaFX XFileTransfer (JFXFileTransfer) was developed with JDK 9.0.4. Upgrading to a JDK version higher than JDK 11 may require you to adapt the deprecated JFX APIs—if they exist. I’m making the SWING package available here. If you’d like the JavaFX version, just send me a short message via my DNH mailbox.
Both Swing and JavaFX package offer the same look and feel and functionality and are thread-safe. They allow the simultaneous sending and receiving of data. However, the appearance of JavaFX is somehow finer and can be easily customized with CSS (Cascading Style Sheets), e.g., font, color, size, etc. To ensure the transmission, both participants must agree on two tokens (sending and receiving) that are in the range of 0 to 256, resulting in 65536 possibilities. Large files (up to 256 TB) can be transferred. An exception will occur if this limit is exceeded.
The XFileTransfer package consists of six Java files:
- XFileTransfer.java: the main application
- Xfer.java: the peer-to-peer thread
- Tools.java: the static peer-to-peer methods
- Utils.java: some helpful static methods such as IPv6, etc.
- OnlyNumeric.java: ensures that the JTextField only accepts numeric input
- PromptText.java: as the name suggests, it is used to display the standard prompt in the JTextField
In addition to the Java source code, there is an image globe.png which should be in the icons directory because of the following line in XFileTransfer.java:
setIconImage(ImageIO.read(XFileTransfer.class.getResource("icons/globe.png")));
The icon Globe.png
![]()
On Windows 11 (JFX version)
On Ubuntu 24.04
XFileTransfer.java
package xfer;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.util.*;
import java.nio.file.*;
import java.awt.event.*;
import java.nio.channels.*;
import java.util.concurrent.*;
//
import javax.swing.*;
import javax.imageio.ImageIO;
// Joe Schwarz (C)
public class XFileTransfer extends JFrame {
//
private String x = System.getProperty("os.name").equals("Linux")? "\\":"/";
private String uHome = System.getProperty("user.home");
private ExecutorService pool = Executors.newFixedThreadPool(64);
private JTextField tFile, tIP, tXs, tXr, tPort, tSave, tHome;
private ServerSocketChannel server = null;
private JComboBox<String> serverIP;
private boolean end = false;
private JTextArea msg;
private JLabel lab;
// java xfer.XFileTransfer remoteIP@port localIP@port
public static void main(String... argv) throws Exception {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
new XFileTransfer(argv);
}
// Constructor
public XFileTransfer(String... argv) throws Exception {
setTitle("XFileTransfer");
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
setIconImage(ImageIO.read(XFileTransfer.class.getResource("icons/globe.png")));
String fiName = "$HOME"+File.separator+"AnyName";
//
serverIP = Utils.ipList();
msg = new JTextArea(10, 40);
JScrollPane jsp = new JScrollPane(msg);
msg.setEditable(false);
lab = new JLabel("Please specify Server Port & IP version");
tXs = new JTextField("1", 3);
tXs.addKeyListener((KeyListener)new OnlyNummeric(tXs));
tXr = new JTextField("2", 3);
tXs.addKeyListener((KeyListener)new OnlyNummeric(tXr));
tSave = new JTextField("$HOME"+File.separator+"Downloads", 32);
tSave.addFocusListener((FocusListener)new PromptText(tSave.getText(), tSave));
tFile = new JTextField(fiName, 32);
tFile.addFocusListener((FocusListener)new PromptText(tFile.getText(), tFile));
if (argv.length >= 1 && argv[0].indexOf("@") > 0) {
int p = argv[0].indexOf("@");
tIP = new JTextField(argv[0].substring(0, p), 32);
try {
p = Integer.parseInt(argv[0].substring(p+1));
tPort = new JTextField(""+p, 5);
} catch (Exception ex) {
tPort = new JTextField("0", 5);
}
} else {
tIP = new JTextField(Utils.IPv6(), 32);
tPort = new JTextField("0", 5);
}
//
tIP.addFocusListener((FocusListener)new PromptText(tIP.getText(), tIP));
tPort.addKeyListener((KeyListener)new OnlyNummeric(tPort));
tPort.addFocusListener((FocusListener)new PromptText(tPort.getText(), tPort));
if (argv.length == 2) {
int p = argv[1].indexOf("@");
serverIP.setSelectedIndex(argv[1].startsWith("IPv6")?1:0);
if (p > 0) try {
p = Integer.parseInt(argv[1].substring(p+1));
tHome = new JTextField(""+p, 5);
} catch (Exception ex) {
tHome = new JTextField("0", 5);
} else tHome = new JTextField(argv[1], 5);
} else tHome = new JTextField("0", 5);
tHome.addFocusListener((FocusListener)new PromptText(tHome.getText(), tHome));
tHome.addKeyListener((KeyListener)new OnlyNummeric(tHome));
tHome.addActionListener(e -> {
startSVR(false);
});
tXs.addKeyListener((KeyListener)new OnlyNummeric(tXs));
tXs.addActionListener(e -> {
tXr.requestFocusInWindow();
});
tXr.addKeyListener((KeyListener)new OnlyNummeric(tXr));
tFile.addActionListener(e -> {
tIP.requestFocusInWindow();
});
tIP.addActionListener(e -> {
tPort.requestFocusInWindow();
});
JButton SEND = new JButton("SEND");
SEND.addActionListener(e -> {
if (!startSVR(false)) return;
send(Tools.getPort(tPort, msg));
});
JButton RECEIVE = new JButton("RETRIEVE");
RECEIVE.addActionListener(e -> {
if (!startSVR(false)) return;
retrieve(Tools.getPort(tPort, msg));
});
JButton EXIT = new JButton("EXIT");
EXIT.addActionListener(e -> {
try {
end = true;
pool.shutdownNow();
TimeUnit.MICROSECONDS.sleep(200);
} catch (Exception ex) { }
System.exit(0);
});
JPanel cm = new JPanel(); cm.add(lab);
JPanel ch = new JPanel(); ch.add(new JLabel("Server")); ch.add(serverIP);
ch.add(new JLabel("@Port")); ch.add(tHome);
JPanel ct = new JPanel(); ct.add(new JLabel("SendToken (1...255)")); ct.add(tXs);
ct.add(new JLabel("RetrieveToken (1...255)")); ct.add(tXr);
JPanel cs = new JPanel(); cs.add(new JLabel("Save Folder: ")); cs.add(tSave);
JPanel c0 = new JPanel(); c0.add(new JLabel("File / FolderName")); c0.add(tFile);
JPanel c1 = new JPanel(); c1.add(new JLabel("remoteServer IP")); c1.add(tIP);
c1.add(new JLabel("@Port")); c1.add(tPort);
JPanel c2 = new JPanel(); c2.add(SEND); c2.add(RECEIVE); c2.add(EXIT);
//
JPanel north = new JPanel(new java.awt.GridLayout(6, 0));
north.add(cm); north.add(ch); north.add(ct); north.add(cs);
north.add(c0); north.add(c1);
add("North", north);
add("Center", jsp);
add("South", c2);
//
setSize(650,520);
setVisible(true);
startSVR(true);
}
//
private boolean startSVR(boolean b) {
if (server != null) return true;
String tmp = tHome.getText();
int port = 0;
try {
port = Integer.parseInt(tmp);
tXs.requestFocusInWindow();
} catch (Exception ex) {
port = 0;
}
if (port == 0) {
if (!b) {
msg.append("ERROR: Invalid HomePort: "+tmp+"\n");
msg.setCaretPosition(msg.getDocument().getLength());
}
tHome.requestFocusInWindow();
tHome.setText("0");
return false;
}
final int lPort = port;
tHome.setEnabled(false);
String IP = (String)serverIP.getSelectedItem();
lab.setText("XFileServer "+IP+"@"+port+" is running");
msg.setText("Selected Server "+IP+"\n");
msg.setCaretPosition(msg.getDocument().getLength());
pool.execute(() -> {
try { // FileServer
server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(IP.substring(6), lPort));
server.setOption(StandardSocketOptions.SO_RCVBUF, 65536);
while (!end) pool.execute(new Xfer(server.accept(), (JFrame)this, msg, tSave, Tools.getToken(tXs, tXr)));
} catch (Exception ex) {
if (!end) {
pool.shutdownNow();
ex.printStackTrace();
System.exit(0);
}
}
if (server != null) try {
server.close();
} catch (Exception ex) { }
});
try { // wait for Pool Service
TimeUnit.MICROSECONDS.sleep(10);
} catch (Exception ex) { }
return true;
}
//
private void send(final int sPort) {
if (sPort > 0) pool.execute(() -> {
String fileName = tFile.getText().trim().replace(x, File.separator).replace("$HOME", uHome);
File file = new File(fileName);
if (!file.exists()){
msg.append(fileName+" is unknown.\n");
msg.setCaretPosition(msg.getDocument().getLength());
return;
}
try {
byte[] token = Tools.getToken(tXs, tXr);
//ByteBuffer bbuf = ByteBuffer.allocate(65536);
ByteBuffer bbuf = ByteBuffer.allocateDirect(65536);
byte[] fName = fileName.substring(fileName.lastIndexOf(File.separator)+1).getBytes();
SocketChannel soc = SocketChannel.open(new InetSocketAddress(tIP.getText(), sPort));
soc.socket().setSendBufferSize(65536);
soc.socket().setTcpNoDelay(true);
soc.socket().setKeepAlive(true);
//
long sum, t0 = 0;
byte[] buf = new byte[2+fName.length];
System.arraycopy(fName, 0, buf, 2, fName.length);
msg.append("send "+fileName+"...\n");
if (file.isDirectory()) { // directory
if (file.listFiles() == null) {
msg.append("Dictory "+fileName+" is empty.\n");
msg.setCaretPosition(msg.getDocument().getLength());
soc.close();
return;
}
System.arraycopy(new byte[] { token[0], (byte)0x01 }, 0, buf, 0, 2);
soc.write(ByteBuffer.wrap(buf, 0, buf.length));
soc.read(bbuf); // wait for Reply
ArrayList<String> list = new ArrayList<>(256);
t0 = System.nanoTime();
sum = Tools.sendDir(soc, bbuf, list, fileName);
Utils.showLog(this, "Send to: "+tIP.getText(), list, sum);
} else { // it's a file
sum = file.length();
if (sum == 0) {
msg.append("File "+fileName+" is empty.\n");
msg.setCaretPosition(msg.getDocument().getLength());
soc.close();
return;
}
System.arraycopy(new byte[] { token[0], (byte)0x00 }, 0, buf, 0, 2);
soc.write(ByteBuffer.wrap(buf, 0, buf.length));
soc.read(bbuf); // wait for Reply
t0 = System.nanoTime();
Tools.sendFile(soc, bbuf, fileName);
}
t0 = System.nanoTime()-t0;
String time = t0 > 1000000000? String.format("Total(Sec.): %.2f", (float)t0/1000000000):
String.format("Total(milliSec.): %.2f", (float)t0/1000000);
String size = sum < 1048576? String.format("(%.3f KB)", (float)sum/1024):
String.format("(%.3f MB)", (float)sum/1048576);
msg.append(String.format("Sent %s %s to Server %s@%d - %s\n", fileName, size, tIP.getText(), sPort, time));
msg.setCaretPosition(msg.getDocument().getLength());
soc.close();
} catch (Exception ex) {
ex.printStackTrace();
msg.append("Failed to connect to Server:"+tPort.getText()+"\n");
msg.setCaretPosition(msg.getDocument().getLength());
}
});
}
//
private void retrieve(final int rPort) {
if (rPort > 0) pool.execute(() -> {
try {
byte[] token = Tools.getToken(tXs, tXr);
String fileName = tFile.getText().trim().replace(x, File.separator);
byte[] fName = fileName.getBytes(); // in byte array
SocketChannel soc = SocketChannel.open(new InetSocketAddress(tIP.getText(), rPort));
soc.socket().setReceiveBufferSize(65536); // 64KB
soc.socket().setTcpNoDelay(true);
soc.socket().setKeepAlive(true); // retrieveToken + fileName
//
byte[] buf = new byte[2+fName.length];
System.arraycopy(new byte[] { token[1], (byte)0x01 }, 0, buf, 0, 2);
System.arraycopy(fName, 0, buf, 2, fName.length);
soc.write(ByteBuffer.wrap(buf, 0, buf.length));
//ByteBuffer bbuf = ByteBuffer.allocate(65536);
ByteBuffer bbuf = ByteBuffer.allocateDirect(65536);
// request from remote for file/directory
long t0 = 0;
long sum = soc.read(bbuf);
buf = new byte[(int)sum];
bbuf.flip().get(buf, 0, (int)sum);
if ((new String(buf, 0, (int)sum)).startsWith("Unknown")) {
msg.append(fileName+" is unknown\n");
msg.setCaretPosition(msg.getDocument().getLength());
soc.close();
return;
}
String sDir = tSave.getText().trim().replace("$HOME", uHome).replace(x, File.separator);
msg.append("Retrieve "+fileName+"...\n");
if (buf[0] == (byte)0x01) { // it's Directory
sum = fileName.lastIndexOf(File.separator)+1;
ArrayList<String> list = new ArrayList<>(256);
t0 = System.nanoTime();
sum = Tools.retrieveDir(soc, bbuf, list, sDir, fileName.substring((int)sum));
Utils.showLog(this, "Retrieve from: "+tIP.getText(), list, sum);
} else { // it's File
t0 = System.nanoTime();
sum = Tools.retrieveFile(soc, bbuf, sDir, fileName, uHome);
}
t0 = System.nanoTime()-t0;
String time = t0 > 1000000000? String.format("Total(Sec.): %.2f", (float)t0/1000000000):
String.format("Total(milliSec.): %.2f", (float)t0/1000000);
String size = sum < 1048576? String.format("(%.3f KB)", (float)sum/1024):
String.format("(%.3f MB)", (float)sum/1048576);
msg.append(String.format("Retrieve %s %s from %s@%d - %s\n", fileName, size, tIP.getText(), rPort, time));
msg.setCaretPosition(msg.getDocument().getLength());
soc.close();
} catch (Exception ex) {
ex.printStackTrace();
msg.append("Failed to connect to Server:"+tPort.getText()+"\n");
msg.setCaretPosition(msg.getDocument().getLength());
}
});
}
}
Xfer.java
package xfer;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.awt.*;
import java.util.*;
import java.nio.file.*;
import java.util.zip.*;
import java.awt.event.*;
import java.nio.channels.*;
import java.util.concurrent.*;
//
import javax.swing.*;
import javax.imageio.ImageIO;
// Joe Schwarz
public class Xfer implements Runnable {
public Xfer(SocketChannel soc, JFrame jf, JTextArea msg, JTextField tSave, byte[] token) {
this.tSave = tSave;
this.token = token;
this.soc = soc;
this.msg = msg;
this.jf = jf;
}
private SocketChannel soc;
private JTextField tSave;
private JTextArea msg;
private byte[] token;
private JFrame jf;
public void run() {
try {
soc.socket().setTcpNoDelay(true);
soc.socket().setSendBufferSize(65536);
soc.socket().setReceiveBufferSize(65536);
//ByteBuffer bbuf = ByteBuffer.allocate(65536);
ByteBuffer bbuf = ByteBuffer.allocateDirect(65536);
String remote = soc.socket().getInetAddress().getHostAddress();
String uHome = System.getProperty("user.home");
String x = System.getProperty("os.name").equals("Linux")? "\\":"/";
//
long sum = soc.read(bbuf);
byte[] buf = new byte[(int)sum];
bbuf.flip().get(buf, 0, (int)sum);
String fileName = (new String(buf, 2, (int)sum-2)).replace("$HOME", uHome).replace(x, File.separator);
//
if (buf[0] == token[0]) { // send from remote
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x00 }, 0, 1));
String sDir = tSave.getText().trim().replace("$HOME", uHome).replace(x, File.separator);
if (buf[1] == (byte)0x01) {
ArrayList<String> list = new ArrayList<>(256);
sum = Tools.retrieveDir(soc, bbuf, list, sDir, fileName);
Utils.showLog(jf, "Received from: "+remote, list, sum);
} else sum = Tools.retrieveFile(soc, bbuf, sDir, fileName, uHome);
String size = sum < 1048576? String.format("(%.3f KB)", (float)sum/1024):
String.format("(%.3f MB)", (float)sum/1048576);
msg.append(String.format("Sent %s %s by %s\n", fileName, size, remote));
msg.setCaretPosition(msg.getDocument().getLength());
} else if (buf[0] == token[1]) { // retrieve from remote
if (fileName.startsWith("$HOME")) fileName = fileName.replace("$HOME", uHome);
File file = new File(fileName);
if (!file.exists()) {
buf = ("Unknown: "+fileName).getBytes();
soc.write(ByteBuffer.wrap(buf, 0, buf.length));
soc.close();
return;
}
if (file.isDirectory()) {
ArrayList<String> list = new ArrayList<>(256);
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x1, (byte)0x0} , 0, 2));
sum = Tools.sendDir(soc, bbuf, list, fileName);
Utils.showLog(jf, "Retrieved by: "+remote, list, sum);
} else {
sum = file.length();
if (sum == 0) {
buf = ("Unknown or empty "+fileName).getBytes();
soc.write(ByteBuffer.wrap(buf, 0, buf.length));
soc.close();
return;
}
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x00, (byte)0x0 } , 0, 2));
Tools.sendFile(soc, bbuf, fileName);
}
String size = sum < 1048576? String.format("(%.3f KB)", (float)sum/1024):
String.format("(%.3f MB)", (float)sum/1048576);
msg.append(String.format("%s %s is retrieved from %s\n",fileName, size, remote));
msg.setCaretPosition(msg.getDocument().getLength());
}
} catch (Exception ex) {
ex.printStackTrace();
}
try {
soc.close();
} catch (Exception e) { }
}
}
Utils.java
package xfer;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import java.nio.channels.*;
//
import javax.swing.*;
// Joe Schwarz
public class Utils {
private static boolean linux = System.getProperty("os.name").equals("Linux");
private static String uHome = System.getProperty("user.home");
//
public static void showLog(JFrame jf, String title, java.util.List<String> list, long sum) {
String x = linux? "\\":"/";
JDialog dialog = new JDialog(jf, title);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
Container dContainer = dialog.getContentPane();
dContainer.setLayout(new BorderLayout());
JTextArea area = new JTextArea(10, 40);
area.setEditable(false);
//
for (String s:list) area.append("- "+s+System.lineSeparator());
area.append((sum < 1048576? String.format("\nTotal: %.3f KB.", (float)sum/1024):
String.format("\nTotal: %.3f MB.", (float)sum/1048576))+System.lineSeparator());
area.setCaretPosition(area.getDocument().getLength());
JScrollPane jsp = new JScrollPane(area);
dContainer.add(jsp, BorderLayout.CENTER);
JTextField tf = new JTextField("$HOME"+File.separator+"Downloads"+File.separator+"log.txt", 32);
tf.addFocusListener((FocusListener)new PromptText(tf.getText(), tf));
JButton SAVE = new JButton("SAVED in");
SAVE.addActionListener(e -> {
String fName = tf.getText().trim().replace("$HOME", uHome).replace(x, File.separator);
try (FileOutputStream fout = new FileOutputStream(fName, false)) {
fout.write((title+System.lineSeparator()).getBytes());
fout.write(area.getText().getBytes());
fout.flush();
fout.close();
} catch (Exception ex) {
JOptionPane.showMessageDialog(jf, "Can't save to "+fName);
}
dialog.dispose();
});
JPanel panel = new JPanel();
panel.add(SAVE); panel.add(tf);
dContainer.add(panel, BorderLayout.SOUTH);
dialog.setBounds(132, 132, 700, 500);
dialog.setVisible(true);
}
// get IPv6 of this localhost
public static String IPv6() {
try{
return InetAddress.getLocalHost().getHostAddress();
} catch (Exception ex) { }
return "localhost";
}
//
public static JComboBox<String> ipList() {
java.util.List<String> list = new ArrayList<>(32);
try {
Enumeration nicEnum = NetworkInterface.getNetworkInterfaces();
while(nicEnum.hasMoreElements()) {
NetworkInterface ni=(NetworkInterface) nicEnum.nextElement();
Enumeration addrEnum = ni.getInetAddresses();
while(addrEnum.hasMoreElements()) {
InetAddress ia = (InetAddress) addrEnum.nextElement();
String ipv6 = ia.getHostAddress();
int p = ipv6.indexOf("%");
if (linux) {
if (ipv6.startsWith("192.168")) list.add(ipv6);
if (ipv6.indexOf(":0:") < 0 && p > 0) list.add(ipv6.substring(0, p));
} else if (p < 0 && ipv6.indexOf(":0:") < 0) {
list.add(ipv6);
}
}
}
} catch(Exception _e) { }
int a = list.size();
String ips[] = null;
if (a == 0) {
ips = new String[] { "IPv4: " +IPv6() };
} else if (!linux) {
ips = new String[2]; // take first and last
ips[1] = "IPv6: "+list.get(list.size()-1);
ips[0] = "IPv4: "+list.get(1);
} else {
ips = new String[2]; // take first and last
ips[1] = "IPv6: "+list.get(1);
ips[0] = "IPv4: "+list.get(2);
}
return new JComboBox<>(ips);
}
}
Tools.java
package xfer;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.util.*;
import java.nio.channels.*;
//
import javax.swing.*;
// Joe Schwarz
public class Tools {
public static int getPort(JTextField tPort, JTextArea msg) {
int port = 0;
try {
port = Integer.parseInt(tPort.getText());
} catch (Exception ex) { port = 0; }
if (port == 0) {
msg.append("ERROR: Invalid RemotePort: 0\n");
msg.setCaretPosition(msg.getDocument().getLength());
tPort.requestFocusInWindow();
}
return port;
}
//
public static byte[] getToken(JTextField tXs, JTextField tXr) {
byte[] token = new byte[2];
try {
token[0] = (byte)(Integer.parseInt(tXs.getText()) & 0xFF);
} catch (Exception ex) { token[0] = (byte)0x01; }
try {
token[1] = (byte)(Integer.parseInt(tXr.getText()) & 0xFF);
} catch (Exception ex) { token[1] = (byte)0x02; }
if (token[1] == token[0]) {
if (token[0] == (byte)0xFF) token[1] = (byte)0x01;
else token[1] = (byte)(token[0] + 1);
}
return token;
}
//
public static long sendDir(SocketChannel soc, ByteBuffer bbuf, List<String> list, String dir) throws Exception {
long len, sum = 0;
len = dir.lastIndexOf(File.separator);
String pfx = dir.length() == (int)len? "":dir.substring((int)len+1)+File.separator;
File[] files = new File(dir).listFiles();
byte[] buf = new byte[512];
//
if (files != null) for (File file : files) {
bbuf.clear();
byte[] name = file.getName().getBytes();
if (file.isDirectory()) { // directory recursive
bbuf.put((byte)0x01); // 0x01: directory
bbuf.put(name, 0, name.length);
soc.write(bbuf.flip());
bbuf.clear();
soc.read(bbuf); // synchronized
sum += sendDir(soc, bbuf, list, file.getAbsolutePath());
} else { // It's a file
len = file.length();
if (len > 0) {
bbuf.put((byte)0x00); // file
bbuf.putLong(len); // file length
bbuf.put(name, 0, name.length);
soc.write(bbuf.flip());
// wait for synchronized
bbuf.clear();
soc.read(bbuf);
bbuf.clear();
list.add(file.getAbsolutePath()+" ("+len+" bytes)");
FileChannel fc = (new FileInputStream(file)).getChannel();
while (fc.read(bbuf) > 0) {
soc.write(bbuf.flip());
bbuf.clear();
}
fc.close();
sum += len;
soc.read(bbuf);
}
}
}
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x02, (byte)0x03 }, 0, 2));
soc.read(bbuf); // wait for synchronized signal
return sum;
}
//
public static void sendFile(SocketChannel soc, ByteBuffer bbuf, String fileName) throws Exception {
bbuf.clear();
FileChannel fc = (new FileInputStream(fileName)).getChannel();
while (fc.read(bbuf) > 0) {
soc.write(bbuf.flip());
bbuf.clear();
}
fc.close();
}
// java XFileTransfer 192.168.0.70@1234 IPv4@5678
// java XFileTransfer 192.168.0.244@5678 IPv4@1234
public static long retrieveDir(SocketChannel soc, ByteBuffer bbuf, List<String> list,
String sDir, String dir) throws Exception {
if (!sDir.endsWith(File.separator)) sDir += File.separator;
//
String HOME = sDir+dir;
File file = new File(HOME);
if (!file.exists()) file.mkdir();
byte[] buf = new byte[512];
long len, a, sum = 0;
while (true) {
bbuf.clear();
a = soc.read(bbuf);
bbuf.flip();
byte b = bbuf.get();
if (b == (byte)0x02) {
if (bbuf.get() == (byte)0x03) break;
} else if (b == (byte)0x01) { // directory
bbuf.get(buf, 0, (int)a-1);
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x00 }, 0, 1));
sum += retrieveDir(soc, bbuf, list, HOME, new String(buf, 0, (int)a-1));
} else {
len = bbuf.getLong();
bbuf.get(buf, 0, (int)a-9);
String fn = HOME+File.separator+(new String(buf, 0, (int)a-9));
// synchronized
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x00 }, 0, 1));
FileChannel fc = (new FileOutputStream(fn, false)).getChannel();
//
a = 0;
while (a < len) {
bbuf.clear();
a += soc.read(bbuf);
fc.write(bbuf.flip());
}
fc.close();
sum += len;
list.add(fn+" ("+len+" bytes)"); //synchronized signal
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x00 }, 0, 1));
}
}
// send synchronized signal
soc.write(ByteBuffer.wrap(new byte[] { (byte)0x00 }, 0, 1));
return sum;
}
// c:/joeapp/xfile/XFileTransfer.java
// c:\joeapp\xfile\XFileTransfer.java
public static long retrieveFile(SocketChannel soc, ByteBuffer bbuf, String sDir, String fileName, String uHome) throws Exception {
bbuf.clear();
long sum = soc.read(bbuf);
byte[] buf = new byte[(int)sum];
bbuf.flip().get(buf, 0, (int)sum);
if ((new String(buf, 0, (int)sum)).startsWith("Unknown")) {
soc.close();
return 0;
}
int n = fileName.lastIndexOf(File.separator)+1;
if (!sDir.endsWith(File.separator)) sDir = sDir+File.separator;
fileName = sDir+fileName.substring(n);
//
if (fileName.startsWith("$HOME")) fileName = fileName.replace("$HOME", uHome);
FileChannel fc = (new FileOutputStream(fileName, false)).getChannel();
fc.write(bbuf.flip());
bbuf.clear();
while ((n = soc.read(bbuf)) > 0) {
fc.write(bbuf.flip());
bbuf.clear();
sum += n;
}
fc.close();
return sum;
}
}





83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?