簡體   English   中英

讀取輸入拋出 java.io.EOFException

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM