问题
I have the following code which transfers file via Sockets. How do I send the file name?
Socket socket = new Socket("localhost", port);//machine name, port number
File file = new File(fileName);
// Get the size of the file
long length = file.length();
if (length > Integer.MAX_VALUE)
{
System.out.println("File is too large.");
}
byte[] bytes = new byte[(int) length];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
int count;
while ((count = bis.read(bytes)) > 0)
{
out.write(bytes, 0, count);
}
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
回答1:
You can invent your own protocol for your socket. If all you need is a filename and data, DataOutputStream.writeUTF is easiest:
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
try (DataOutputStream d = new DataOutputStream(out)) {
d.writeUTF(fileName);
Files.copy(file.toPath(), d);
}
The peer must use the same protocol, of course:
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
try (DataInputStream d = new DataInputStream(in)) {
String fileName = d.readUTF();
Files.copy(d, Paths.get(fileName));
}
回答2:
Use a character that can never be in a file name - such as a null (0x00
, \0
, whatever you want to call it). Then send a 64 bit integer that indicates how long, in bytes, the file is (make sure you don't run into buffer overflows, little endian/big endian issues, etc... just test all edge cases). Then send the file data. Then the ending socket will know which part is the file name, the file length and the file data, and will even be ready for the next file name if you want to send another.
(if file names can be arbitrary characters including control characters, ouch! Maybe send a 64 bit integer length of file name, the file name, a 64 bit integer length of file data, the file data, repeat ad infinitum?)
EDIT: To send a 64 bit integer over a socket, send its constituent bytes in a specific order, and make sure sender and receiver agree on the order. One example of how to do this is How to convert a Java Long to byte[] for Cassandra?
回答3:
I tried to wrap a buffer which cause MalfuctionUTF and putting it on try-with resource closes the underlining socket stream and cause connection reset exception
Following code worked for me
Client
DataOutputStream d = new DataOutputStream(out);
d.writeUTF(filename);
d.writeLong(length);
Server
DataInputStream d = new DataInputStream(in);
filename = d.readUTF();
fileLength = d.readLong();
来源:https://stackoverflow.com/questions/15649972/how-do-i-send-file-name-with-file-using-sockets-in-java