通过套接字的Java文件传输修剪最后的字节

时间:2017-06-10 14:08:34

标签: java file sockets file-transfer transfer

我一直在尝试使用文件传输功能创建一个Messenger,但最后我仍然有太多的空字符。任何时候我使用文件长度去除它们,由于某种原因,更多的文件被剥离,它只是变得一团糟。我没有使用任何Java 7或更高版本的元素,因为我希望它与Java 6和Windows 98(grandma的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();
            }
        }
    }

}

1 个答案:

答案 0 :(得分:0)

在上面的代码中,我认为它会导致以下错误。 首先,你应该添加一个数字来表示文件名的长度。就像这样:

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方法可以读取从输入流到字节数组的长度字节,直到流结束。

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并不正确,并且不应该在末尾添加数字。适当的方法是将文件数据写入套接字输出流FileTransmitter,并且不做任何其他事情。就像这样:

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

在另一方面,当你从socket oupustream读取字节到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;
      }
 }