文件传输中的数据丢失 - JAVA?

3
我有一个文件服务器和一个文件客户端,当客户端连接时,服务器会发送一个文件。这是一个简单的程序,只是为了理解背后的概念。
我能够使用1024个缓冲区将文件从服务器发送到客户端。问题在于接收到的文件始终比原始文件少约0.01MB。因此,mp3文件会丢失一些信息,视频文件则无法播放。
我在服务器和客户端的while循环中添加了一些println语句。我发现我的服务器没有发送整个文件。
  //Server
  byte [] mybytearray  = new byte [1024];    
  FileInputStream fis = new FileInputStream(myFile);
  BufferedInputStream bis = new BufferedInputStream(fis);
  bis.read(mybytearray,0,mybytearray.length);
  OutputStream os = sock.getOutputStream();
  System.out.println("Sending...\n mybytearray length:"+mybytearray.length+"file   length:"+(int)myFile.length());
  int read, readTotal=0;
  while ((read = fis.read(mybytearray,0,mybytearray.length)) != -1) { 

      os.write(mybytearray, 0, read);
      System.out.println("File REad:"+read+"readtotal:"+readTotal); //*
      readTotal += read;
}
  System.out.println("Final File Read:"+read+" Final readtotal:"+readTotal);
  os.flush();
  sock.close();
  } 

打印输出语句的输出结果为:
Sending...
mybytearray length:1024file length:12767554
File REad:1024readtotal:0
File REad:1024readtotal:1024
.............and a lot of it...and then
File REad:1024readtotal:12756992
File REad:1024readtotal:12758016
File REad:322readtotal:12759040
Final File Read:-1 Final readtotal:12759362

文件长度为12767554,最后读取的总数为12759362应该是相等的。我不明白为什么最后读取的值较低[322],即使它仍然可以有1024。
任何帮助都会受到赞赏。 谢谢。
//Client
int read;
int totalRead = 0;

while ((read = is.read(mybytearray,0,mybytearray.length)) != -1) {
        bos.write(mybytearray, 0 , read);

        totalRead += read;
        System.out.println("\nread:"+read+"\ntotalread: "+totalRead);
}
System.out.println("Final File Read:"+read+" Final readtotal:"+totalRead);
bos.write(mybytearray, 0 , read);  //57 Line in FileClient.java
bos.flush();

我又尝试发送一个文件,这次是txt类型的。下面是我的服务器输出:
Sending...
mybytearray length:1024file length:1232
File REad:1024readtotal:0
File REad:208readtotal:1024
Final File Read:-1 Final readtotal:1232

还有这个在客户端的

read:208
totalread: 1232
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
   Final File Read:-1     Final readtotal:1232

at java.lang.System.arraycopy(Native Method)
at java.io.BufferedOutputStream.write(Unknown Source)
at FileClient.main(FileClient.java:57)

readtotal值相同,但有时会出现此错误,有时不会。

[大修改-完整客户端代码]

public class FileClient{
 public static void main (String [] args ) throws IOException {

long start = System.currentTimeMillis();
int bytesRead;
int current = 0;
final JFrame f = new JFrame("Sample");
f.getContentPane().setLayout(new FlowLayout());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(590,490);
f.setVisible(true);
// localhost for testing
Socket sock = new Socket("localhost",13267);
System.out.println("Connecting...");
File f1=new File(RecieveObject(sock));


// receive file
byte [] mybytearray  = new byte [1024];
InputStream is = sock.getInputStream();


FileOutputStream fos = new FileOutputStream(f1);
ProgressMonitorInputStream nn= new ProgressMonitorInputStream(f,"reading",is);
BufferedOutputStream bos = new BufferedOutputStream(fos);
 /*   bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;


do {
   bytesRead =
      is.read(mybytearray, current, (mybytearray.length-current));
   System.out.println("mybytesarray length: "+mybytearray.length+"\ncurrent:"+current+"\nbytesread: "+bytesRead);
   if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);

bos.write(mybytearray, 0 , current);
bos.flush();
 */
int read;
int totalRead = 0;
//InputStream clientInputStream = clientSocket.getInputStream();
while ((read = is.read(mybytearray,0,mybytearray.length)) != -1) {
        bos.write(mybytearray, 0 , read);

        totalRead += read;
        System.out.println("\nread:"+read+"\ntotalread: "+totalRead);
}
System.out.println("Final File Read:"+read+" Final readtotal:"+totalRead);
 //   bos.write(mybytearray, 0 , read);
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
sock.close();

}
public static  String RecieveObject(Socket s) {
    String str = null;
    try{
    ObjectInputStream is = new ObjectInputStream(s.getInputStream());



            str =(String)is.readUTF();


    }
    catch(IOException ex){}
    return str;
}   

}


我刚刚看到我发送的视频文件大小为41046 KB,传输后现在变成了41040 KB。我不知道6 KB去哪了? - Nikhar
在客户端删除第57行后,我没有收到任何错误提示,但在传输后仍然丢失了6 KB的文件。 - Nikhar
如果您原来的问题已经得到解答,那么您可能需要从您最后一次编辑中提出新的问题。新问题需要具体说明哪些代码存在问题(例如,第57行在哪里?)。 - BillRobertson42
实际上,这是一个尚未解决的相同问题,所以我认为不应该创建一个新的...客户端代码中while循环后的第57行是bos.write。我刚刚将其删除,虽然我没有收到错误,但我仍然会丢失大约6KB或有时4KB的数据? - Nikhar
问题已经解决了,我用try/catch包围了代码。使用相同的示例(prev),这次没有数据丢失,确切地获得了41046 KB,但这只是暂时的,现在我又丢失了一些KB,我已经删除了ProgressMonitor(虽然它没有起作用),现在我将从客户端/服务器中删除ObjectXXXXXXStreams,并进行检查? - Nikhar
2个回答

6
您错过了文件开头的内容(前1024个字节),这是由于您的第五行代码(包括注释)导致的。在读取输入并推进它时,您没有将其发送给客户端。请删除此行代码:
bis.read(mybytearray,0,mybytearray.length);

此外,在循环中您没有使用BufferedInputStream。如果您仍然想要缓冲读取,请在此处使用bis.read代替fis.read - 或者完全删除BufferedInputStream

您的另一个问题是,您正在客户端上读取最终字节,然后再次进入循环。is.read再次被调用。而不是返回-1,它抛出了一个IOException,因为套接字的另一侧已关闭。因此,bos.flush()和bos.close()没有被调用,您的最终字节永远不会写入磁盘。为了解决这个问题,尝试在关闭之前调用sock.shutdownOutput。无论如何,您都需要在此周围添加一些适当的异常处理。


是的,我认为我错过了文件的开头部分,刚刚听到收到的mp3文件。我会尝试一下。 - Nikhar
@NikharSharma - 你的 readTotal 是否仍然存在差异?是否可能缺失的字节现在是由于客户端代码(可能由于类似于此处的问题)而不是服务器代码引起的?也许您可以同时发布客户端代码? - ziesemer
是的,我认为我不应该假设,但是,实际上我错过了什么数据,我失去了6KB的视频,并没有出现任何错误,但是这次我尝试了一个简单的1232 B文本文件,却出现了错误。?? - Nikhar
@NikharSharma - 再次提醒,在客户端,您不需要最终的bos.write(mybytearray, 0 , read);。这将导致无效输出,但并不一定解释您为什么会得到异常。我认为在客户端代码的省略部分中可能有其他有用的细节。此外,请包括每个示例的实际预期文件大小。 - ziesemer
1
让我们在聊天中继续这个讨论 - Nikhar
显示剩余2条评论

1
byte [] mybytearray  = new byte [1024];    
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...\n mybytearray length:"+mybytearray.length+"filelength:"+(int)myFile.length());
int read, readTotal=0;
while ((read = bis.read(mybytearray,0,mybytearray.length)) != -1) { 
    os.write(mybytearray, 0, read);
    System.out.println("File REad:"+read+"readtotal:"+readTotal); //*
    readTotal += read;
}
System.out.println("Final File Read:"+read+" Final readtotal:"+readTotal);
os.flush();
sock.close();
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接