遇到一个问题,client端和server端通过tcp socket传输图片,假设是本地文件test.png,我想把文件名和图片一起传输过去,试了很久,发现一直解码不正确,不知道该怎么办,小弟对io操作确实不是很熟悉,贴一下代码,求指点。求高人指点啊,我也不知道我为什么只能给62分最高,本来应该给100分的,先感激不尽了。
Client端public class Client {
private static final int PORT = 6666;
private static final String IP = "127.0.0.1";
private static String subject = "Floating";
        private static String fileName = "test.png";
        private static String filePath = "/Users/junxiyin/Desktop/"+fileName;

public static void main(String[] args){

OutputStream outputStream = null;
FileInputStream fis = null;

try{
Socket s = new Socket(IP, PORT);   
fis = new FileInputStream(filePath);  
outputStream = s.getOutputStream();  
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));



StringBuffer sb = new StringBuffer();
sb.append(fileName + "/n/joshua");
   

byte[] buffer = new byte[8192];  //建立一个buffer,将数据暂时存储,避免多次读写硬盘
int temp = 0 ;
while((temp = fis.read(buffer))!= -1){    //从inputStream读取数据并将其存储在buffer中
sb.append(new String(buffer,0,temp));
}

bw.write(sb.toString());
System.out.println("from the client " + sb.toString());

fis.close();
bw.flush();    
bw.close();
    s.close();

} catch (Exception e) {
e.printStackTrace();
}
}
}Server端public class Server {
public static void main(String[] args){
InputStream is = null;
BufferedReader br = null;
String temp = null;
OutputStream os = null;
StringBuffer str = new StringBuffer();
try {
ServerSocket ss = new ServerSocket(6666);
Socket s = ss.accept();
is = s.getInputStream();
br = new BufferedReader(new InputStreamReader(is));

while((temp = br.readLine()) != null){  
      str.append(temp);
}

String[] strDest = str.toString().split("/n/joshua");
       
if(strDest.length != 2)
                System.err.println("error: strDest.length != 2");
        System.out.println(strDest.length);
        
                // fileName
                System.out.println("fileName: " + strDest[0]);
        
                // file
                System.out.println("file: " + strDest[1]);
        
      
                File file = new File("/Users/junxiyin/Desktop/testCopy.png");
                os = new FileOutputStream(file);
                os.write(strDest[2].getBytes());
os.flush();
os.close();
        
                is.close();
s.close();

}catch (IOException e) {
    e.printStackTrace();
        }
}
}

解决方案 »

  1.   

    String[] strDest = str.toString().split("/n/joshua");这肯定有问题的,str.toString一是编码不确定,一是你怎么保证图片字节流中不包含joshua的编码。好点的办法是:自己定义一个包的格式:比如从前到后,
    2B:包总长
    1B:文件名长
    XB:文件名数据
    YB:图片数据
    其中B表示字节,XB表示文件名实际长度,YB表示图片数据长度
      

  2.   

    给你抄点代码,大体是2楼那个意思。
    定义个结构,先传文件名长度,通过这个长度取文件名,再得到开始下载的文件偏移量。
    资源下载:http://download.csdn.net/detail/AFer198215/3647106
    服务器端:public class DownloadResponsetHandler extends ResponsetHandler{
    private static final Logger logger = Logger.getLogger(DownloadResponsetHandler.class);

    public void process() throws Exception {
    byte[] buffer = new byte[512];
    int readLen = 0;
    RandomAccessFile fileIn = null;

    //4,这个数必需小512
    int fileNameSize = 0;
    //int(n)
    String fileName = null;
    //8
    long startPosit = 0;

    readLen = read(buffer, 0, 4);
    if(4 > readLen){
    logger.error("数据错误.");
    return;
    }
    fileNameSize = Utility.byte2Int(buffer,0);

    readLen = read(buffer, 0, fileNameSize);
    if(fileNameSize > readLen){
    logger.error("数据错误.");
    return;
    }
    fileName = new String(buffer, 0, fileNameSize, RequestCommand.CHARSET_ENCODING);

    readLen = read(buffer, 0, 8);
    if(8 > readLen){
    logger.error("数据错误.");
    return;
    }
    startPosit = Utility.byte2Long(buffer,0);

    try{
    fileIn = new RandomAccessFile(fileName, "r");
    fileIn.seek(startPosit);

    while(-1 != (readLen = fileIn.read(buffer))){
    write(buffer,0,readLen);
    }
    }finally{
    try{
    if(null != fileIn) fileIn.close();
    }catch(Exception ex){
    }
    }

    logger.debug("发送数据完成.");
    }

    }
    客户端:static void t5(){
    byte[] buffer = new byte[1000];
    int readLen = 0;
    Socket c = null;
    ClientFactory cf = SpringTool.getBean("clientFactory");
    InputStream in = null;
    OutputStream out = null;
    // String file = "D:\\test\\1\\1234.txt";
    // String file = "d:\\test\\1\\中文.txt";
    String file = "D:\\test\\1\\edass4a.deply.2.zip";
    File storeFile = new File("d:\\test\\2", "clone_edass4a.deply.2.zip");
    OutputStream fileOut = null;
    byte[] bs = null;

    try {
    c = cf.getClient(RequestCommand.DOWNLOAD);
    in = c.getInputStream();
    out = c.getOutputStream();

    bs = file.getBytes(RequestCommand.CHARSET_ENCODING);
    out.write(Utility.int2Byte(bs.length));
    // out.write(new byte[]{0x0, 0x0, 0x0, 0x3});
    out.write(bs);
    out.write(Utility.long2Byte(0L));
    out.flush();

    fileOut = new FileOutputStream(storeFile);
    while(-1 != (readLen = in.read(buffer))){
    fileOut.write(buffer, 0, readLen);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    try{
    if(null != fileOut) fileOut.close();
    }catch(Exception ex){
    }

    try{
    c.close();
    }catch(Exception ex){
    }
    }

    }
      

  3.   

    不想分开传的话,记得改掉程序中的两个问题:
    ①Server端不要用readLine,会吞掉图片中的一些字节,当它们的值正好等于回车符的时候。和Client端一样用buffer读好了。
    ②在所有字符读写环节,都改用ISO-8859-1编码(默认的是GBK编码),防止图片中某些字节因为无法转换为GBK字符而丢失。
    如果需要代码,我再贴给你。
      

  4.   

    我把server端的readline改掉以后,确实读取的字节数就完全匹配了,但是编码我貌似有点无能为力,试了试用InputStreamReader来包装FileInputStream,但是读取还是不能可否给我一个分开传的代码,可能那样更加可靠,小弟感激不尽了