Java发送文件在接收时总是少8字节

Java发送文件在接收时总是少8字节,java,sockets,Java,Sockets,我的java服务器客户端文件通信有两个问题 我让客户端将文件发送到服务器,服务器接收文件 我的两个问题是: 1) 每当我发送一个文件时,它就会少8个字节(我不知道为什么) 2) 除非关闭套接字,否则文件传输不会完成(少于8个字节),我不希望关闭套接字。我希望我的连接是持久的,那么如何才能从客户端向服务器发送EOF 这是我的客户谁发送文件 public void sendFiles(String file) { try { File myFile = ne

我的java服务器客户端文件通信有两个问题

我让客户端将文件发送到服务器,服务器接收文件

我的两个问题是:

1) 每当我发送一个文件时,它就会少8个字节(我不知道为什么)

2) 除非关闭套接字,否则文件传输不会完成(少于8个字节),我不希望关闭套接字。我希望我的连接是持久的,那么如何才能从客户端向服务器发送EOF

这是我的客户谁发送文件

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源罗。