Java 通过套接字传输文件 trim 最后字节

Java file transfer over Sockets trim last bytes

我一直在尝试创建具有文件传输功能的 Messenger,但最后总是出现太多空字符。每当我使用文件长度来剥离它们时,由于某种原因,更多的文件被剥离并且它变得一团糟。我没有使用任何 Java 7 或更高版本的元素,因为我希望它与 Java 6 和 Windows 98(祖母的 PC)兼容。

我还在文件中添加了很多随机空字符,我不确定如何避免这种情况

这是我的代码: 传送

package com.androdome.lunacoffee.management;

import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import com.androdome.lunacoffee.ErrorScreen;
import com.androdome.lunacoffee.SendScreen;

public class FileTransmitter implements Runnable{
    String adds;
    FileInputStream message;
    int filecut = 4096;
    byte[] fileName;
    long fileSize;
    SendScreen send;
    public FileTransmitter(String address, FileInputStream msg, byte[] fnme, SendScreen snd, long l) {
            adds = address;
            send = snd;
            message = msg;
            fileName = fnme;
            fileSize = l;
    }




    public void run()
    {
        try {
            InetAddress add = InetAddress.getByName(adds);
            Socket sock = new Socket(add, 11001);
            DataOutputStream da = new DataOutputStream(sock.getOutputStream());
            PrintWriter output = new PrintWriter(da);
            da.write(fileName);


            da.writeLong(message.getChannel().size());

            byte[] filebuffer = new byte[filecut];
            int g = 0;
            int back = 0;
            while((g = message.read(filebuffer)) != -1)
            {
                if(g != filecut && g > 0)
                {
                    back = g;
                }
                da.write(filebuffer);
                filebuffer = new byte[filecut];
            }
            da.writeInt(back);
            System.out.print(back);

            output.flush();
            output.close();
            send.incrementSent();
        } catch (UnknownHostException e) {
            send.incrementError();
            // TODO Auto-generated catch block
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            new ErrorScreen("Unable to send file", "Your file was not able to send because the host \"" + adds + "\" was not availible!", sw.toString());
            pw.close();
            try {
                sw.close();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        } catch (IOException e) {
            send.incrementError();
            // TODO Auto-generated catch block
            new ErrorScreen("Unable to send file", "Your file was not able to send due to a bad output stream!", e.getMessage());
        }
    }

}

收到:

package com.androdome.lunacoffee.management;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

import com.androdome.lunacoffee.ErrorScreen;
import com.androdome.lunacoffee.FileScreen;
import com.androdome.lunacoffee.Main;

public class FileReciever implements Runnable {
    int bufferSize = 4096;
    int headerSize = 32;
    byte[] filebuffer = new byte[bufferSize];
    byte[] fileheader = new byte[headerSize];
    Main main;
    File downloadfile = new File("tmp");
    File transferFile = new File("dnl.ldf");
    public FileReciever(Main mn)
    {
        main = mn;
    }


    static byte[] trim(byte[] bytes)
    {
        int i = bytes.length - 1;
        while (i >= 0 && bytes[i] == 0)
        {
            --i;
        }

        return Arrays.copyOf(bytes, i + 1);
    }

    public void run() {


        try {
            ServerSocket recieveSocket = new ServerSocket(11001);
            while (this != null) {
                try{
                downloadfile.createNewFile();
                Socket connectionSocket = recieveSocket.accept();
                DataInputStream reader = new DataInputStream(connectionSocket.getInputStream());
                reader.read(fileheader);
                long fileSize = reader.readLong();
                System.out.println(bufferSize);
                filebuffer = new byte[bufferSize];

                String fileName = new String(fileheader);
                fileheader = new byte[headerSize];
                FileOutputStream fw = new FileOutputStream(downloadfile);
                while(reader.read(filebuffer) != -1)
                    {
                        fw.write(filebuffer);
                        filebuffer = new byte[bufferSize];
                    }           
                //reader.readInt();
                reader.close();
                fw.close();
                //RandomAccessFile file = new RandomAccessFile(downloadfile, "Rwd");
                //file.setLength(fileSize); // Strip off the last _byte_, not the last character
                //file.close();

                connectionSocket.close();
                FileScreen fs = new FileScreen(downloadfile, fileName, connectionSocket.getInetAddress().getHostName());
                fs.setVisible(true);
                fs.setLocationRelativeTo(null);
                }
                catch(Exception ex)
                {}
            }
        } catch (IOException e) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            new ErrorScreen("Unable to start the File Recieve Thread", "Luna Messenger may already be running, or another program is using port 11001. Please close any program running on port 11001.", sw.toString());
            pw.close();
            try {
                sw.close();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }

}

在你上面的代码中,我认为它犯了以下错误。 首先,你应该添加一个数字来表示文件名的 length.like this:

da.writeInt(fileName.length);  //the added code
da.write(fileName);

FileReciever上,接收码是:

int fileNameLength = reader.readInt();
fileheader=new byte[fileNameLength];
read(reader,fileheader,0,fileNameLength);

read 方法可以从输入流中读取最多 length 个字节到字节数组中,直到流结束。

public static int read(InputStream in, byte[] b, int off, int len) throws IOException {
    if (len < 0) {
        throw new IndexOutOfBoundsException("len is negative");
    }
    int total = 0;
    while (total < len) {
        int result = in.read(b, off + total, len - total);
        if (result == -1) {
            break;
        }
        total += result;
    }
    return total;
}

其次,FileTransmitter 将文件日期转换为 FileReciever 是不正确的,不应该在 end.The 处添加数字,适当的方法只是写入文件数据在 FileTransmitter 中套接字输出流,并且不要做任何其他 things.Like this:

while((g = message.read(filebuffer)) != -1)
{
     da.write(filebuffer,0,g);
}

另一方面,应该读取多少字节取决于您之前从套接字输入流中读取的字节长度,当您将字节从套接字输出流读取到filebuffer时。接收器代码:

int readLength;
int sumLength=0;
while((readLength=reader.read(filebuffer,0,(int)(fileSize-sumLength>filebuffer.length?filebuffer.length:fileSize-sumLength))) != -1){
      sumLength+=readLength;
      fw.write(filebuffer,0,readLength);
      if(sumLength==fileSize){
          break;
      }
 }