Home > Enterprise >  Reading an input throws java.io.EOFException
Reading an input throws java.io.EOFException

Time:06-13

Trying to read an UTF string from byte array throws EOFException, when I know for a fact that it should not happen. I've attempted to use ByteBuffer and ByteArrayDataOutputStream and OutputStream for writing the data, and then trying to read it with DataInputStream and ByteArrayDataInputStream and DataInputStream with no success. Where am is the code failing and WHY?

The structure of the data is [String, Long, Long], which translates to String, UUID

Methods I've tried to write the data:

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();
}

Writing the data with both methods works fine, but the next parts are where it fails:

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();
}

The data output printed to console results in this: group2��K��&F,��8��m(↑ (Which using string -> bytes converter is '67726f757032efbfbdefbfbd4befbfbdefbfbd26462cefbfbdefbfbd38efbfbdefbfbd6d28e28691') The inputted string is "group2" and inputted UUID is 'd4ef4bc2-db26-462c-9793-389ba56d2818'

The stacktrace from the above method is the following:

[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 

Minimum reproducible:

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;
    }
}

Running the above minimum reproducible produces the following errors:

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) 

CodePudding user response:

If you write bytes, you should read them as bytes. If you want a UTF string, then write a UTF string: output.writeUTF(g.getID()). The readUTF method uses something to determine where to stop reading. I've checked the OpenJDK source code of DataInputStream, and its readUTF method expects the string length first (2 bytes), then it reads that many characters. This is documented in DataInput.readUTF

First, two bytes are read and used to construct an unsigned 16-bit integer in exactly the manner of the readUnsignedShort method . This integer value is called the UTF length and specifies the number of additional bytes to be read. These bytes are then converted to characters by considering them in groups. The length of each group is computed from the value of the first byte of the group. The byte following a group, if any, is the first byte of the next group.

So you can do the same with a ByteBuffer as well. First write the size as a short, then the bytes as UTF8:

var bytes = string.getBytes(StandardCharsets.UTF_8);
buffer.putShort((short) bytes.length);
buffer.put(bytes);

Note the explicit conversion to bytes using UTF-8.

  •  Tags:  
  • java
  • Related