Java通过同一套接字发送字符串(文件名)和文件

Java通过同一套接字发送字符串(文件名)和文件,java,sockets,stream,Java,Sockets,Stream,我会通过套接字发送“filename”和“file”,我能够轻松地发送文件,但当我尝试发送字符串时,例如PrintWriter pw.println()或DataOutputStream或“out.writeUTF()”,文件被发送损坏,我读了很多关于StackOverflow的问题,但没有找到答案,我正在寻找一些例子来发送字符串和文件,你能帮忙吗 服务器 package serverprova; import java.io.BufferedInputStream; import java.

我会通过套接字发送“filename”和“file”,我能够轻松地发送文件,但当我尝试发送字符串时,例如PrintWriter pw.println()或DataOutputStream或“out.writeUTF()”,文件被发送损坏,我读了很多关于StackOverflow的问题,但没有找到答案,我正在寻找一些例子来发送字符串和文件,你能帮忙吗

服务器

package serverprova;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;



public class ServerProva {

final static int porta=8888;//porta server dove si collegano i client

public static void main(String[] args) throws IOException {
    // TODO code application logic here
    ServerSocket serverSocket=null;

    boolean ascoltando=true;

    serverSocket = new ServerSocket(porta);//avvia il server con il  numero di porta
    Socket s;
    BufferedReader br1=null;
     // ******  interfaccia f=new interfaccia);

      boolean r=true;
      BufferedInputStream bis=null;
       Scanner sc;
    FileOutputStream fout;

    while(ascoltando)
        {

        s=serverSocket.accept();// this socket 

    String filename="";
    String nome_cartella="";
    InputStream in = null;
OutputStream out = null;

   DataInputStream inString;


        inString = new DataInputStream(new BufferedInputStream(s.getInputStream()));
       //  filename = inString.readUTF();
       //  nome_cartella = inString.readUTF();



    in = s.getInputStream();



    //out = new FileOutputStream(nome_cartella+"/"+filename);
out = new FileOutputStream("ciao"+"/"+"asd.jpg");

byte[] b = new byte[20*1024];

int i ;


        while((i = in.read(b)) >0){
            out.write(b, 0, i);
        }
        out.close();
in.close();
//inString.close();
s.close();

        }


 }

}
客户

    package clientprova;


import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;


public class ClientProva {
final static int porta=8888;

public static void main(String[] args) throws FileNotFoundException, IOException {
    File file;
    file = new File("kirlian12.jpg");
   InetAddress host = InetAddress.getLocalHost();
Socket sock = new Socket(host.getHostName(), 8888);
   DataOutputStream outString = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));

     //   outString.writeUTF(file.getName());
      //  outString.writeUTF("rivelatore2");
     //   outString.flush();

     byte[] b = new byte[20*1024]; 



                InputStream in = new FileInputStream(file);
        OutputStream out = sock.getOutputStream();

        int i ;

        while ((i = in.read(b)) >0    ) {
            out.write( b , 0 , i);
        }


        out.close();
        in.close();

sock.close();



   }


 }

当我尝试取消注释注释行时,当您使用BufferedInputStream包装InputStream时,我的文件会损坏,后者“拥有”InputStream。这意味着当您调用
readUtf()
时,BufferedInputStream从InputStream读取的字节数可能比读取UTF字符串所需的字节数还要多。所以,当您下次直接访问InputStream时,传输文件的某些部分丢失(因为它以前被读入BufferedInputStream的缓冲区,并且当前驻留在那里)


您必须从两个选项中进行选择:始终使用原始InputStream或始终使用BufferedInputStream。同样的推理也适用于OutputStream(但您通过调用
flush()
)成功地避免了问题的发生。

当您使用BufferedInputStream包装InputStream时,后者“拥有”InputStream。这意味着当您调用
readUtf()
时,BufferedInputStream从InputStream读取的字节数可能比读取UTF字符串所需的字节数还要多。所以,当您下次直接访问InputStream时,传输文件的某些部分丢失(因为它以前被读入BufferedInputStream的缓冲区,并且当前驻留在那里)


您必须从两个选项中进行选择:始终使用原始InputStream或始终使用BufferedInputStream。同样的推理也适用于OutputStream(但您通过调用
flush()
)成功地避免了问题。

请提供一个最小的完整工作示例。@SureshKoya ok使用注释行,我只需要发送1个字符串,对于新手问题,很抱歉,如果您只允许文件名使用一定数量的字节,然后允许文件本身的剩余字节,您可以在收到后轻松解析这些字节。@Manodesra您说我将filename+文件作为单个包发送?我需要一个小例子是的,作为一个单独的包。为文件名分配256个字节,并确保仅将文件名写入字节数组的该部分。然后,字节数组的其余部分将是文件本身的字节。或者你可以有一个8或16字节的头段,告诉你文件名的字节长度和文件的字节长度。然后,您可以在读取标题字节后在收到后轻松解析。请提供一个最小的完整工作示例。@SureshKoya ok使用注释行,我只需要发送1个字符串,对于新手问题很抱歉。如果您只允许文件名使用一定数量的字节,则允许文件本身使用剩余的字节,你可以很容易地解析收到的字节。@ManoDestra你说我把filename+文件作为一个包发送?我需要一个小例子是的,作为一个单独的包。为文件名分配256个字节,并确保仅将文件名写入字节数组的该部分。然后,字节数组的其余部分将是文件本身的字节。或者你可以有一个8或16字节的头段,告诉你文件名的字节长度和文件的字节长度。然后在读取头字节后,您可以很容易地在收到后解析它。好的,但是我不知道如何修复它,而且我找不到任何示例可以理解,如果我选择单独使用InputStream,我应该做什么?只需将
while((I=in.read(b))>0{
替换为
while((I=inString.read(b))>0){
。非常感谢,我是Java新手,现在学习流是最困难的部分。我必须学习更好的Rok,但我不知道如何修复它,而且我找不到任何示例可以理解,如果我选择单独使用InputStream,我应该做什么?只要替换
而((I=in.read(b))>0){
with
while((i=inString.read(b))>0{
。非常感谢,我是Java新手,现在学习流是最难的部分。我必须学习得更好
inString = new DataInputStream(new BufferedInputStream(s.getInputStream()));
filename = inString.readUTF();
nome_cartella = inString.readUTF();
...
in = s.getInputStream();
while((i = in.read(b)) >0){