Java发送文件在接收时总是少8字节
我的java服务器客户端文件通信有两个问题 我让客户端将文件发送到服务器,服务器接收文件 我的两个问题是: 1) 每当我发送一个文件时,它就会少8个字节(我不知道为什么) 2) 除非关闭套接字,否则文件传输不会完成(少于8个字节),我不希望关闭套接字。我希望我的连接是持久的,那么如何才能从客户端向服务器发送EOF 这是我的客户谁发送文件Java发送文件在接收时总是少8字节,java,sockets,Java,Sockets,我的java服务器客户端文件通信有两个问题 我让客户端将文件发送到服务器,服务器接收文件 我的两个问题是: 1) 每当我发送一个文件时,它就会少8个字节(我不知道为什么) 2) 除非关闭套接字,否则文件传输不会完成(少于8个字节),我不希望关闭套接字。我希望我的连接是持久的,那么如何才能从客户端向服务器发送EOF 这是我的客户谁发送文件 public void sendFiles(String file) { try { File myFile = ne
public void sendFiles(String file) {
try {
File myFile = new File(file);
long length = myFile.length();
byte[] buffer = new byte[8192];
System.out.println(length);
FileInputStream in = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(in);
BufferedOutputStream outF = new BufferedOutputStream(sock.getOutputStream());
out.print("%SF%" + length + "$" + myFile.getName() + "#");
out.flush();
int count;
while ((count = in.read(buffer)) > 0) {
outF.write(buffer, 0, count);
}
outF.flush();
in.close();
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
接收文件的服务器
我正在传递文件名和长度,但只使用文件名。但是,我不知道是否需要使用文件的长度,以防出现EOF或其他情况。请指教
此外,代码挂起
while ((count = this.sock.getInputStream().read(buffer)) > 0) {
由于没有EOF,我不知道如何实现
public void recvFile(String fileName, int length) {
try {
byte[] buffer = new byte[8192];
FileOutputStream outF = new FileOutputStream("/Users/Documents" +fileName);
BufferedOutputStream bos = new BufferedOutputStream(outF);
int count = length;
while ((count = this.sock.getInputStream().read(buffer)) > 0) {
bos.write(buffer, 0, count);
}
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
更新:我已经删除了建议中不需要的flush()。另外,我已经在另一个类中测试了这段代码,它工作了,但在客户端-服务器聊天中不工作。谁能告诉我为什么
任何帮助或提示都将不胜感激。
谢谢。我建议您先发送文件大小和/或文件属性。。。您可以尝试广泛用于此任务的HTTP。。。
另一个建议是,您只需在其他TCP端口上打开另一个连接来发送文件(这实际上是FTP发送文件的方式)我怀疑您遇到的问题在于您没有显示的代码中 在本例中,您可以通过同一个流发送多个消息或文件
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.SocketChannel;
/**
* Created by peter on 1/25/15.
*/
public class DataSocket implements Closeable {
private final Socket socket;
private final DataOutputStream out;
private final DataInputStream in;
public DataSocket(Socket socket) throws IOException {
this.socket = socket;
this.out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
this.in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}
@Override
public void close() throws IOException {
out.flush();
socket.close();
}
// message format is length as UTF-8 encoded name, 32-bit int followed by data.
public void writeMessage(String description, byte[] bytes) throws IOException {
out.writeUTF(description);
out.writeInt(bytes.length);
out.write(bytes);
out.flush();
}
public byte[] readMessage(String[] description) throws IOException {
description[0] = in.readUTF();
int length = in.readInt();
byte[] bytes = new byte[length];
in.readFully(bytes);
return bytes;
}
public void writeFile(File file) throws IOException {
long length = file.length();
if (length > Integer.MAX_VALUE) throw new IllegalArgumentException("length=" + length);
out.writeUTF(file.toString());
out.writeInt((int) length);
byte[] buffer = new byte[(int) Math.min(length, 32 * 1024)];
try (FileInputStream fis = new FileInputStream(file)) {
for (int len; (len = fis.read(buffer)) > 0; ) {
out.write(buffer, 0, len);
}
}
out.flush();
}
public void readFile(File dir) throws IOException {
String fileName = in.readUTF();
int length = in.readInt();
byte[] buffer = new byte[(int) Math.min(length, 32 * 1024)];
try (FileOutputStream fos = new FileOutputStream(new File(dir, fileName))) {
while (length > 0) {
int len = in.read(buffer);
fos.write(buffer, 0, len);
length -= len;
}
}
}
// todo convert to a unit test
public static void main(String[] args) throws IOException {
// port 0 opens on a random free port.
ServerSocket sc = new ServerSocket(0);
DataSocket ds1 = new DataSocket(new Socket("localhost", sc.getLocalPort()));
DataSocket ds2 = new DataSocket(sc.accept());
sc.close();
// now ds1 and ds2 are connected.
File f = File.createTempFile("deleteme","");
f.deleteOnExit();
try (FileOutputStream fos = new FileOutputStream(f)) {
fos.write(new byte[10001]);
}
// send a request
ds1.writeMessage("Send me the file", new byte[0]);
String[] desc = { null };
byte[] data = ds2.readMessage(desc);
if (!desc[0].equals("Send me the file")) throw new AssertionError();
// return a response
ds2.writeFile(f);
f.delete();
if (f.exists()) throw new AssertionError();
ds1.readFile(new File(""));
if (f.length() != 10001) throw new AssertionError("length="+f.length());
ds1.close();
ds2.close();
System.out.println("Copied a "+f.length()+" file over TCP");
}
}
recvFile
函数应仅使用长度。你想让它准确地读取长度
字节,对吗?是的,我的意思是只读取文件的长度,然后退出函数,但它没有按预期工作。另外,它会发送文件,但不完整。您认为它会如何工作?(您的函数实际上没有将length
参数的值用于任何事情,因此您不可能期望它知道读取那么多字节)不,我暂时不使用它,因为我尝试了一段时间,但一点运气都没有,因为执行卡在这一行,“((count=this.sock.getInputStream().read(缓冲区))>0){“并且在我关闭套接字之前不会移动,这是我不想要的。我留下了未使用的长度,让别人告诉我如何使用itTCP流,其工作方式与文件流类似。如何从文件中读取准确的字节数?实际上,他确实发送了长度和文件名(编码奇怪,但w/e)@nneonneo:是吗?我看到名称和长度打印到out
而不是outF
@user3558040我该如何使用HTTP来实现它?或者如何实现其他建议?谢谢你Hi Deyaa。关于HTTP文件上传协议的解释:对于FTP,我建议:@alk:Good catch…但是out
没有定义,所以可能是这样的更让人困惑的是:PHi Peter,非常感谢您的回答。正如您所知,是的,目前我正在使用两个流(文本的printWriter和Scanner)和另一个流(in和Outp)来发送/接收文件。我是否应该更改客户端和服务器中的所有流,以便它们都可以(发送文本和文件)使用DataOutputStream和DataInputStream?然后复制您在writeFile方法中编写的内容并在我的sendFiles方法中使用它,复制您的readFiles方法并在我的recvFile方法中使用它。这样,我将按照您在前面的回答中提到的方式统一流,那么它应该可以正常工作?@Deyaa如果您这样做,它将消除一个常见的er源罗。