2016-12-03 2 views
0

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

Вот мой код:

Я пытаюсь отправить файл банки через сокет, но когда я пытаюсь открыть файл банки с другой стороны, файл, кажется, поврежден. Как я могу это исправить?

Сервер:

object server extends App { 
    import java.net._ 
    import java.io._ 
    import scala.io._ 

    import scala.io.Source 

    val server = new ServerSocket(9999) 

    //Master should ping the slave actor to request for jar file 
    while (true) { 
     val s = server.accept() 
     val in = new BufferedSource(s.getInputStream()).getLines() 
     val out = new PrintStream(s.getOutputStream()) 

     val filename = "mapReduce.jar" 
     for (line <- Source.fromFile(filename, "ISO-8859-1").getLines)  { 
      out.println(line) 
      // println(line) 
     } 


     out.flush() 
     s.close() 
    } 
} 

Наряду с Клиентом:

object client extends App { 
    import java.net._ 
    import java.io._ 
    import scala.io._ 
    import java.util.jar._ 

    val s = new Socket(InetAddress.getByName("localhost"), 9999) 
    lazy val in = new BufferedSource(s.getInputStream()).getLines() 
    val out = new PrintStream(s.getOutputStream()) 

    out.println("Give me the jar file!") 
    out.flush() 

    val file = new File("testmapReduce.jar") 
    val bw = new BufferedWriter(new FileWriter(file)) 
    while(in.hasNext) { 
     val buf = in.next() 
     bw.write(buf) 
     // println(buf) 
    } 


    s.close() 
    bw.close() 


    println("Done!") 
    val jar = new JarFile(file) //this part fails 
} 
+0

Кувшин файл эффективно «двоичный» файл. Для обработки файла используются текстовые методы (например, println и getLines). Написание файла с помощью println будет вставлять символы CR и/или LF в выходной поток. Я подозреваю, что вы этого не хотите, и именно это вызывает проблему коррупции. Попробуйте использовать print вместо println. – mangotang

+0

Спасибо @mangotang, это имеет большой смысл. Я попытался изменить println для печати, но проблема все еще существует. – Leaf

+0

Я грамотный Java, но не грамотный Scala, поэтому я не знаком с некоторыми из API, которые вы используете здесь. Я * удивляюсь *, если ваше использование getLines может также помочь в решении проблемы. Если вы используете getLines в двоичном файле, читатель будет читать до любого байта, который выглядит как CR, отбрасывает CR и возвращает строку. Таким образом, возможно, что getLines/getLine фильтрует любой CR (который, поскольку это двоичный файл, не является по-настоящему CR, а на самом деле просто двоичным значением в ваших данных, равным CR [десятичный 13]). – mangotang

ответ

2

Source, PrintStream и т.д., предназначены для борьбы с текстом, а не двоичные данные. Они преобразуют данные как для чтения, так и для записи в соответствии с набором символов, который они используют («iso-8859-1» в вашем случае). Не используйте их для чтения/записи двоичных данных.

Если вам просто нужно отправить байт, не заморачиваться с их интерпретации:

val f = new FileInputStream(filename) 
    val bos = new BufferedOutputStream(out) 
    Stream.continually(f.read).takeWhile(_ != -1).foreach(bos.write) 
    f.close 
    bos.close 
+0

Спасибо за ответ. Не могли бы вы объяснить, что именно эта строка; Stream.continually (r.read) .takeWhile (_! = -1) .foreach (bos.write) делает? к чему относится r.read? – Leaf

+0

'r.read' была опечаткой. Должно быть 'f.read'. Что касается остальной части его, я думаю, если вы просто прочитаете то, что он говорит слева направо, это будет довольно понятным: постоянно читайте материал с 'f', пока не получите -1, и напишите его на' bos'. – Dima

+0

Я пробовал это, но я получаю java.nio.charset.MalformedInputException: Длина ввода = 1 ошибка, которую я предполагаю, мне нужно указать некоторую кодировку. Где я могу добавить кодировку и какую кодировку использовать? – Leaf

Смежные вопросы