FileOutputStream写出0个字节

时间:2017-06-08 14:54:44

标签: java sockets ubuntu server fileoutputstream

我正在尝试通过Java套接字将文件从一个程序发送到另一个程序。我的代码基于this question问题是在托管服务器的Ubuntu机器上,发送的文件大小为0字节。代码已经在我的Windows笔记本电脑上的本地连接上工作,所以可能问题有与远程连接有关吗?

服务器代码:

int g = Integer.parseInt(in.readLine());
if(g > -1) {
    InputStream fIn = client.getInputStream();
    for(int i = 0; i < g; i++) {
        String name = in.readLine();
        byte[] bytes = new byte[16*1024];
        File f = new File("plugins/" + name + ".jar");
        if(!f.exists()) f.createNewFile();
        FileOutputStream fOut = new FileOutputStream(f);
        int count;
        while ((count = fIn.read(bytes)) >= 0) {
            fOut.write(bytes, 0, count);
        }
        fOut.flush();
        fOut.close();
    }
    System.out.println("[" + client.getRemoteSocketAddress().toString() + "] added " + g + " new plugins.");
    client.close();
}else{
    client.close();
}

客户代码:

JFileChooser fd = new JFileChooser("C:\\");                         
fd.setFileSelectionMode(JFileChooser.FILES_ONLY);
fd.setMultiSelectionEnabled(true);
fd.setFileFilter(new FileNameExtensionFilter(null,"jar"));
int r = fd.showOpenDialog(null);
if(r == JFileChooser.APPROVE_OPTION) {
    File[] files = fd.getSelectedFiles();
    OutputStream fOut = sock.getOutputStream();
    out.println(files.length);
    for(File f : files) {
        out.println(f.getName().split("\\.")[0]);
        byte[] bytes = new byte[16 * 1024];
        FileInputStream fIn = new FileInputStream(f);
        int count;
        while ((count = fIn.read(bytes)) >= 0) {
            fOut.write(bytes, 0, count);
        }
        fIn.close();
    }
}else{
    out.println(-1);
}
sock.close();

0 bytes

1 个答案:

答案 0 :(得分:0)

如评论中所述,您的代码中存在不同的问题。

要识别单个文件的结尾,您只需在用分号分隔的文件名后添加文件大小;

out.println(f.getName().split("\\.")[0] + "; size" + f.length());

在服务器端,你累积文件大小读/写停止读取文件的内容关闭它并读取下一行(文件名/文件大小)。

如评论中所述,存在不同的问题。 您使用fInfOut,但不清楚它们是如何定义的。 在客户端,您使用fOut,而Socket OutputStream被命名为&#39; out&#39;。 在服务器端类似的事情。您从in读取文件数,但之后从Socket获取InputStream(再次?)并将其用作fIn。取决于您的in可能有效还是无效。

同时从readLine中读取来自InputStream的行以及二进制内容也不是那么简单。在我的示例代码中,我使用了DataInputStream,即使readLine方法已被弃用。

示例还使用&#34;尝试使用资源&#34;语法,以确保在异常情况下所有资源(Streams,Sockets)都关闭。

示例没有说明如何处理服务器端的文件大小这取决于您。

该示例在一台计算机上完全可运行,并显示如何根据您的代码通过套接字复制单个文件。

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class ClientServerSocketExample {

    private static class Server {

        public void run() throws IOException {

            try (ServerSocket serverSocket = new ServerSocket(41000, 10, InetAddress.getLocalHost())) {
                try (Socket client = serverSocket.accept()) {

                    try (DataInputStream in = new DataInputStream(client.getInputStream())) {

                        int g = Integer.parseInt(in.readLine());

                        if(g > -1) {
                            for(int i = 0; i < g; i++) {
                                String[] filenameAndSize = in.readLine().split(";");
                                String name = filenameAndSize[0];
                                byte[] bytes = new byte[16*1024];
                                File f = new File("/tmp/" + name + ".jar");
                                if(!f.exists()) f.createNewFile();
                                try (FileOutputStream fOut = new FileOutputStream(f)) {
                                    int count;
                                    while ((count = in.read(bytes)) >= 0) {
                                        fOut.write(bytes, 0, count);
                                    }
                                    fOut.flush();
                                }
                            }
                            System.out.println("[" + client.getRemoteSocketAddress().toString() + "] added " + g + " new plugins.");


                        }
                    }
                }
            }
        }

    }

    private static class Client {

        public void run() throws IOException {
            try (Socket socket = new Socket()) {
                socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 41000) );

                sendFiles(socket);
            }
        }

        private static void sendFiles(Socket sock) throws IOException {
            File[] files = new File[]{new File("some.jar")}; 
            OutputStream fOut = sock.getOutputStream();
            PrintStream out = new PrintStream(fOut);

            out.println(files.length);
            for(File f : files) {
                out.println(f.getName().split("\\.")[0] + "; size" + f.length());

                byte[] bytes = new byte[16 * 1024];
                try (FileInputStream fIn = new FileInputStream(f)) {
                    int count;
                    while ((count = fIn.read(bytes)) >= 0) {
                        out.write(bytes, 0, count);
                    }
                    out.flush();
                }
            }
        }


    }



    public static void main(String ... args) throws IOException, InterruptedException {
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    new Server().run();
                } catch (IOException ioe) {
                    System.out.println(ioe);
                }


            }

        }).start();

        System.out.println("Waiting for the Server to come up");
        Thread.sleep(500);

        new Client().run();
    }

}

当客户端发送\r作为新行分隔符并且文件以\n开头时,此解决方案可能存在问题。服务器可能会将\n计为行分隔符的一部分,并且文件将损坏(将丢失一个字节)。