[英]Reading an input throws java.io.EOFException
當我知道它不應該發生時,嘗試從字節數組中讀取 UTF 字符串會引發 EOFException。 我嘗試使用 ByteBuffer 和 ByteArrayDataOutputStream 和 OutputStream 來寫入數據,然后嘗試使用 DataInputStream 和 ByteArrayDataInputStream 和 DataInputStream 讀取它,但沒有成功。 代碼在哪里失敗,為什么?
數據的結構是[String, Long, Long],翻譯成String, UUID
我嘗試寫入數據的方法:
ByteBuffer buffer = ByteBuffer.allocate(g.getID().getBytes().length + Long.BYTES * 2);
buffer.put(g.getID().getBytes());
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
ByteArrayOutputStream output_ = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(output_);
try {
output.write(g.getID().getBytes());
output.writeLong(uuid.getMostSignificantBits());
output.writeLong(uuid.getLeastSignificantBits());
api.sendToServers(KaranteeniPermsKeys.GLOBAL_GROUP_CHANGED, output_.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
使用這兩種方法寫入數據都可以正常工作,但接下來的部分是失敗的地方:
ByteArrayDataInput input2 = msg.getDataInput();
String group2 = input2.readUTF(); // EOFException
long mostSignificant2 = input2.readLong();
long leastSignificant2 = input2.readLong();
UUID uuid2 = new UUID(mostSignificant2, leastSignificant2);
ByteArrayInputStream input_ = new ByteArrayInputStream(msg.getMessageBytes());
DataInputStream input = new DataInputStream(input_);
try {
String group = input.readUTF(); // EOFException
long mostSignificant = input.readLong();
long leastSignificant = input.readLong();
UUID uuid = new UUID(mostSignificant, leastSignificant);
// rest of the code
} catch(IOException e) {
e.printStackTrace();
}
打印到控制台的數據輸出結果如下: group2��K��&F,��8��m(↑ (which using string -> bytes converter is '67726f757032efbfbdefbfbd4befbfbdefbfbd26462cefbfbdefbfbd38efbfbdefbfbd6d28e28691') 輸入的字符串是“group2”,輸入的 UUID 是'd4ef4bc2-db26-462c-9793-389ba56d2818'
上述方法的堆棧跟蹤如下:
[14:33:04 WARN]: java.lang.IllegalStateException: java.io.EOFException
[14:33:04 WARN]: at com.google.common.io.ByteStreams$ByteArrayDataInputStream.readUTF(ByteStreams.java:458)
[14:33:04 WARN]: at KaranteeniPerms.jar//net.karanteeni.karanteeniperms.spigot.groups.BungeeListeners.onGlobalGroupChanged(BungeeListeners.java:80) [14:33:04 WARN]: at SockExchange-1.1.1-all.jar//com.gmail.tracebachi.SockExchange.Messages.ReceivedMessageNotifier.lambda$notify$1(ReceivedMessageNotifier.java:94) [14:33:04 WARN]: at SockExchange-1.1.1-all.jar//com.gmail.tracebachi.SockExchange.Scheduler.AwaitableExecutor.lambda$wrapTask$0(AwaitableExecutor.java:182) [14:33:04 WARN]: at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[14:33:04 WARN]: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[14:33:04 WARN]: at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [14:33:04 WARN]: at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [14:33:04 WARN]: at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [14:33:04 WARN]: at java.base/java.lang.Thread.run(Thread.java:833)
[14:33:04 WARN]: Caused by: java.io.EOFException
[14:33:04 WARN]: at java.base/java.io.DataInputStream.readFully(DataInputStream.java:203)
[14:33:04 WARN]: at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:614)
[14:33:04 WARN]: at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:570)
[14:33:04 WARN]: at com.google.common.io.ByteStreams$ByteArrayDataInputStream.readUTF(ByteStreams.java:456)
[14:33:04 WARN]: ... 9 more
最小可重復性:
import java.nio.ByteBuffer;
import com.google.common.io.ByteArrayDataInput;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.UUID;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
public class MinData {
public static void main(String[] args) {
String name = "group2";
UUID uuid = UUID.randomUUID();
try {
method1Input(ByteStreams.newDataInput(method1Output(name, uuid)));
} catch(Exception e) {
e.printStackTrace();
}
try {
method1Input(ByteStreams.newDataInput(method2Output(name, uuid)));
} catch(Exception e) {
e.printStackTrace();
}
try {
method2Input(method1Output(name, uuid));
} catch(Exception e) {
e.printStackTrace();
}
try {
method2Input(method2Output(name, uuid));
} catch(Exception e) {
e.printStackTrace();
}
}
public static void method1Input(ByteArrayDataInput input) {
String group = input.readUTF(); // EOFException
long mostSignificant = input.readLong();
long leastSignificant = input.readLong();
UUID uuid = new UUID(mostSignificant, leastSignificant);
}
public static void method2Input(byte[] bytes) {
ByteArrayInputStream input_ = new ByteArrayInputStream(bytes);
DataInputStream input = new DataInputStream(input_);
try {
String group = input.readUTF(); // EOFException
long mostSignificant = input.readLong();
long leastSignificant = input.readLong();
UUID uuid = new UUID(mostSignificant, leastSignificant);
// rest of the code
} catch(IOException e) {
e.printStackTrace();
}
}
public static byte[] method1Output(String text, UUID uuid) {
ByteBuffer buffer = ByteBuffer.allocate(text.getBytes().length + Long.BYTES * 2);
buffer.put(text.getBytes());
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
return buffer.array();
}
public static byte[] method2Output(String text, UUID uuid) {
ByteArrayOutputStream output_ = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(output_);
try {
output.write("group2".getBytes());
output.writeLong(uuid.getMostSignificantBits());
output.writeLong(uuid.getLeastSignificantBits());
return output_.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
運行上述最小可重現性會產生以下錯誤:
15:03:34 [SEVERE] java.lang.IllegalStateException: java.io.EOFException
15:03:34 [SEVERE] at com.google.common.io.ByteStreams$ByteArrayDataInputStream.readUTF(ByteStreams.java:458)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.method1Input(KaranteeniPerms.java:101)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.<init>(KaranteeniPerms.java:75)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
15:03:34 [SEVERE] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
15:03:34 [SEVERE] at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.enablePlugin(PluginManager.java:341)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.loadPlugins(PluginManager.java:250)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCord.start(BungeeCord.java:271)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCordLauncher.main(BungeeCordLauncher.java:67)
15:03:34 [SEVERE] at net.md_5.bungee.Bootstrap.main(Bootstrap.java:15)
15:03:34 [SEVERE] Caused by: java.io.EOFException
15:03:34 [SEVERE] at java.io.DataInputStream.readFully(DataInputStream.java:197)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:609)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:564)
15:03:34 [SEVERE] at com.google.common.io.ByteStreams$ByteArrayDataInputStream.readUTF(ByteStreams.java:456)
15:03:34 [SEVERE] ... 11 more
15:03:34 [SEVERE] java.lang.IllegalStateException: java.io.EOFException
15:03:34 [SEVERE] at com.google.common.io.ByteStreams$ByteArrayDataInputStream.readUTF(ByteStreams.java:458)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.method1Input(KaranteeniPerms.java:101)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.<init>(KaranteeniPerms.java:81)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
15:03:34 [SEVERE] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
15:03:34 [SEVERE] at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.enablePlugin(PluginManager.java:341)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.loadPlugins(PluginManager.java:250)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCord.start(BungeeCord.java:271)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCordLauncher.main(BungeeCordLauncher.java:67)
15:03:34 [SEVERE] at net.md_5.bungee.Bootstrap.main(Bootstrap.java:15)
15:03:34 [SEVERE] Caused by: java.io.EOFException
15:03:34 [SEVERE] at java.io.DataInputStream.readFully(DataInputStream.java:197)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:609)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:564)
15:03:34 [SEVERE] at com.google.common.io.ByteStreams$ByteArrayDataInputStream.readUTF(ByteStreams.java:456)
15:03:34 [SEVERE] ... 11 more
15:03:34 [SEVERE] java.io.EOFException
15:03:34 [SEVERE] at java.io.DataInputStream.readFully(DataInputStream.java:197)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:609)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:564)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.method2Input(KaranteeniPerms.java:112)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.<init>(KaranteeniPerms.java:87)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
15:03:34 [SEVERE] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
15:03:34 [SEVERE] at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.enablePlugin(PluginManager.java:341)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.loadPlugins(PluginManager.java:250)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCord.start(BungeeCord.java:271)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCordLauncher.main(BungeeCordLauncher.java:67)
15:03:34 [SEVERE] at net.md_5.bungee.Bootstrap.main(Bootstrap.java:15)
15:03:34 [SEVERE] java.io.EOFException
15:03:34 [SEVERE] at java.io.DataInputStream.readFully(DataInputStream.java:197)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:609)
15:03:34 [SEVERE] at java.io.DataInputStream.readUTF(DataInputStream.java:564)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.method2Input(KaranteeniPerms.java:112)
15:03:34 [SEVERE] at net.karanteeni.karanteeniperms.bungee.KaranteeniPerms.<init>(KaranteeniPerms.java:93)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
15:03:34 [SEVERE] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
15:03:34 [SEVERE] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
15:03:34 [SEVERE] at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.enablePlugin(PluginManager.java:341)
15:03:34 [SEVERE] at net.md_5.bungee.api.plugin.PluginManager.loadPlugins(PluginManager.java:250)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCord.start(BungeeCord.java:271)
15:03:34 [SEVERE] at net.md_5.bungee.BungeeCordLauncher.main(BungeeCordLauncher.java:67)
15:03:34 [SEVERE] at net.md_5.bungee.Bootstrap.main(Bootstrap.java:15)
如果你寫字節,你應該把它們當作字節來讀。 如果你想要一個 UTF 字符串,那么寫一個 UTF 字符串: output.writeUTF(g.getID())
。 readUTF
方法使用某些東西來確定在哪里停止閱讀。 我檢查了DataInputStream
的 OpenJDK 源代碼,它的readUTF
方法首先需要字符串長度(2 個字節),然后讀取那么多字符。 這記錄在DataInput.readUTF
首先,讀取兩個字節並使用 readUnsignedShort 方法的方式構造一個無符號的 16 位整數。 這個整數值稱為 UTF 長度,並指定要讀取的附加字節數。 然后通過分組考慮將這些字節轉換為字符。 每個組的長度是根據組的第一個字節的值計算的。 組后面的字節(如果有的話)是下一組的第一個字節。
所以你也可以對ByteBuffer
做同樣的事情。 首先將大小寫為short,然后將字節寫為UTF8:
var bytes = string.getBytes(StandardCharsets.UTF_8);
buffer.putShort((short) bytes.length);
buffer.put(bytes);
請注意使用 UTF-8 顯式轉換為字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.