SocketException:sendto失败:EBADF(坏文件描述符)

我尝试从Android手机通过套接字发送数据。 我发送PDF文件到打印机进行打印。 在Java中它工作正常,但Kotlin抛出SocketException:sendto失败:EBADF(坏文件描述符),但是用Kotlin代码,打印机无论打印什么。

全堆栈跟踪:

java.net.SocketException: sendto failed: EBADF (Bad file descriptor) at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:542) at libcore.io.IoBridge.sendto(IoBridge.java:511) at java.net.PlainSocketImpl.write(PlainSocketImpl.java:500) at java.net.PlainSocketImpl.-wrap1(PlainSocketImpl.java) at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:266) at java.io.OutputStream.write(OutputStream.java:82) at java.io.DataOutputStream.writeBytes(DataOutputStream.java:156) at com.example.print.printerserver.connectors.OutputHelper.writeFooter(OutputHelper.java:22) at com.example.print.printerserver.connectors.PrinterConnector.fillPJL(PrinterConnector.kt:30) at com.example.print.printerserver.connectors.PrinterConnector.access$fillPJL(PrinterConnector.kt:8) at com.example.print.printerserver.connectors.PrinterConnector$print$1.subscribe(PrinterConnector.kt:17) at io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39) at io.reactivex.Single.subscribe(Single.java:2779) at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89) at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452) at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61) at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818) Caused by: android.system.ErrnoException: sendto failed: EBADF (Bad file descriptor) at libcore.io.Posix.sendtoBytes(Native Method) at libcore.io.Posix.sendto(Posix.java:211) at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:278) at libcore.io.IoBridge.sendto(IoBridge.java:509) 

代码,抛出exception:

 return Single.create { emitter -> try { Socket(ip, port).use { socket -> DataOutputStream(socket.getOutputStream()).use { output -> fillPJL(output, filename, paperSize, copies) emitter.onSuccess("Success printing") } } } catch (e: Exception) { emitter.onError(e) } } 

我相同的Java示例(使用PJL命令):

 return Single.create(new SingleOnSubscribe() { @Override public void subscribe(SingleEmitter emitter) throws Exception { Socket socket = null; DataOutputStream out = null; FileInputStream inputStream = null; try { socket = new Socket(printerIP, printerPort); out = new DataOutputStream(socket.getOutputStream()); DataInputStream input = new DataInputStream(socket.getInputStream()); inputStream = new FileInputStream(file); byte[] buffer = new byte[3000]; final char ESC = 0x1b; final String UEL = ESC + "%-12345X"; final String ESC_SEQ = ESC + "%-12345\r\n"; out.writeBytes(UEL); out.writeBytes("@PJL \r\n"); out.writeBytes("@PJL JOB NAME = '" + filename + "' \r\n"); out.writeBytes("@PJL SET PAPER=" + paperSize.name()); out.writeBytes("@PJL SET COPIES=" + copies); out.writeBytes("@PJL ENTER LANGUAGE = PDF\r\n"); while (inputStream.read(buffer) != -1) out.write(buffer); out.writeBytes(ESC_SEQ); out.writeBytes("@PJL \r\n"); out.writeBytes("@PJL RESET \r\n"); out.writeBytes("@PJL EOJ NAME = '" + filename + "'"); out.writeBytes(UEL); out.flush(); } catch (IOException e) { e.printStackTrace(); emitter.onError(e); } finally { try { if (inputStream != null) inputStream.close(); if (out != null) out.close(); if (socket != null) socket.close(); emitter.onSuccess("Succ"); } catch (IOException e) { e.printStackTrace(); emitter.onError(e); } } } }); 

我的fillPJL函数:

 private fun fillPJL(output: DataOutputStream?, filename: String, paperSize: PaperSize, copies: Int) { val ESC = 0x1b.toChar() val UEL = ESC + "%-12345X" val ESC_SEQ = ESC + "%-12345\r\n" output?.writeBytes(UEL) output?.writeBytes("@PJL \r\n") output?.writeBytes("@PJL JOB NAME = '$filename' \r\n") output?.writeBytes("@PJL SET PAPER=" + paperSize.name) output?.writeBytes("@PJL SET COPIES=" + copies) output?.writeBytes("@PJL ENTER LANGUAGE = PDF\r\n") writeData(output) output?.writeBytes(ESC_SEQ) output?.writeBytes("@PJL \r\n") output?.writeBytes("@PJL RESET \r\n") output?.writeBytes("@PJL EOJ NAME = '\$filename'") output?.writeBytes(UEL) } 

我写数据文件如此:

 fun writeData(output: DataOutputStream) { file.inputStream().use { input -> outputStream.use { it.write(input.readBytes()) } } } 

我解决了我的问题。 为了将数据写入Kotlin的OutputStream中,我使用了:

 file.inputStream().use { input -> outputStream.use { it.write(input.readBytes()) } } 

运算符.use { }在这段代码后关闭了我的OutputStream,但之后我再次使用它。这是一个例外的原因。

我改变了写入数据到OutputStream,所以:

 file.inputStream().use { it.copyTo(outputStream, bufferSize = BUFFER) } 

它正常工作!