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;
}
}
我一直在尝试创建具有文件传输功能的 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;
}
}