Ошибка байта файла в kotlin. Как правильно передать?

Я хочу передать файл с tcp-клиентом на сервер, но файл с изображениями был неправильным.

Мой клиентский код

import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream import org.msgpack.core.MessageBufferPacker import org.msgpack.core.MessagePack import org.msgpack.core.MessageUnpacker import java.io.* import java.net.Socket import java.util.* fun main(args: Array<String>) { fileClient("localhost",1988,"fruit.jpg") } class fileClient (host:String, port:Int, file:String){ var s : Socket ?= null var out = ByteArrayOutputStream() var msg : MessageBufferPacker = MessagePack.newDefaultBufferPacker() init { try { s = Socket(host,port) sendFile(file) }catch (e:Exception){ e.printStackTrace() } } @Throws(IOException::class) fun sendFile(file: String) { val dos = DataOutputStream(s!!.getOutputStream()) val buffer = ByteArray(4096) val filebytes = File(file).readBytes() var msgdata = ByteOutputStream() msg.packString(file) msg.packBinaryHeader(filebytes.size) msg.writePayload(filebytes) msg.close() val data = msg.toByteArray() val datasize = data.size val ins = ByteArrayInputStream(data) dos.writeInt(datasize) while (ins.read(buffer) > 0) { dos.write(buffer) } dos.close() } } 

И мой код сервера

 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream import org.msgpack.core.MessagePack import org.msgpack.core.MessageUnpacker import java.awt.List import java.io.* import java.net.ServerSocket import java.net.Socket import java.text.SimpleDateFormat import java.util.* fun main(args: Array<String>) { var fs = FileServer(1988) fs.start() } class FileServer(port: Int) : Thread() { private var ss: ServerSocket? = null var fileRealName : String ?= null init { try { ss = ServerSocket(port) } catch (e: IOException) { e.printStackTrace() } } override fun run() { while (true) { try { val clientSock = ss!!.accept() saveFile(clientSock) } catch (e: IOException) { e.printStackTrace() } } } @Throws(IOException::class) private fun saveFile(clientSock: Socket) { var msgList = ArrayList<Any>() val dis = DataInputStream(clientSock.inputStream) val msgdata = ByteOutputStream() val buffer = ByteArray(4096) var read = 0 while (true) { val datalen = dis.readInt() // data length if(datalen!= null && datalen >0){ var finaldata = ByteArray(datalen) var process = 0; while (process <= datalen) { read = dis.read(buffer) if (read < 0) { return } msgdata.write(buffer) process += 4096 } println(process.toString() + " "+ datalen.toString()) var allData = msgdata.toByteArray().slice(0..datalen).toByteArray() unpackByte(allData) } } msgdata.close() dis.close() } private fun unpackByte(data:ByteArray){ var unpacker : MessageUnpacker = MessagePack.newDefaultUnpacker(data) var fileName = unpacker.unpackString().toString() var filesize = unpacker.unpackBinaryHeader() var buffer = ByteArray(filesize) unpacker.readPayload(buffer) var fos = FileOutputStream(fileName) fos.write(buffer) fos.close() unpacker.close() } } 

И файл, который я хочу передать, – это введите описание изображения здесь

но после передачи изображение на сервере выглядит следующим образом. введите описание изображения здесь

Как я могу перенести этот файл правильно?

Мне не удалось воспроизвести вашу проблему. Однако я думаю, что нашел ошибку, которая может привести к повреждению передачи файлов.

В коде сервера есть бесконечный цикл, который немедленно возвращается из метода, оставляя остальную часть метода недоступной. Это код очистки, который закрывает соединения и потоки. Вполне возможно, что OutputStream не был должным образом закрыт, и это является причиной повреждения файла.

Вот как выглядит код сервера:

 val datalen = dis.readInt() // data length if (datalen > 0) { var finaldata = ByteArray(datalen) var process = 0; while (process <= datalen) { read = dis.read(buffer) if (read < 0) { break } msgdata.write(buffer) process += 4096 } println(process.toString() + " " + datalen.toString()) val allData = msgdata.toByteArray().slice(0..datalen).toByteArray() unpackByte(allData) } msgdata.close() dis.close() 

while цикл не нужен. Также вы, вероятно, должны просто break цикл, а не return из функции.

PS Рассматривали ли вы использование IOUtils для обработки всех операций чтения / записи IO? Половину вашего кода можно заменить несколькими строками кода, используя эту библиотеку.