Java中如何将多个值存入byte数组并实现读写解析?
Hey there! Let's break this down step by step since you're working on serializing data into a byte array (then Base64-ing it for file storage) for your Java app—great approach, by the way. I’ve built similar systems before, so let’s unpack the details you’re curious about.
First: How writeString() and readString() Usually Work
The core problem with strings is they’re variable-length—you can’t just dump their bytes into the array and expect to read them back reliably. You need a way to signal how many bytes belong to the string. Here’s the standard pattern:
Writing a String to a Byte Array
- Encode the string consistently: Use a fixed charset like
UTF-8(never rely on the default charset—it’s platform-dependent!). - Write the length first: Before the string’s bytes, write a 4-byte integer (Java’s
intsize) that tells the reader exactly how many bytes the string takes up. - Write the string bytes: Dump the encoded bytes right after the length marker.
Simplified implementation:
public static void writeString(ByteArrayOutputStream out, String s) throws IOException { byte[] strBytes = s.getBytes(StandardCharsets.UTF_8); // Write the 4-byte length (big-endian order) out.write((strBytes.length >> 24) & 0xFF); out.write((strBytes.length >> 16) & 0xFF); out.write((strBytes.length >> 8) & 0xFF); out.write(strBytes.length & 0xFF); // Write the actual string bytes out.write(strBytes); }
Reading a String from a Byte Array
- Read the length first: Grab the 4-byte integer to know how many bytes to read for the string.
- Read exactly that many bytes: Use a byte array of the specified length to hold the string data.
- Decode back to a string: Convert the bytes using the same charset used for encoding.
Simplified read implementation:
public static String readString(ByteArrayInputStream in) throws IOException { // Read the 4-byte length (big-endian) int length = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read(); byte[] strBytes = new byte[length]; in.read(strBytes); // Read all bytes for the string return new String(strBytes, StandardCharsets.UTF_8); }
Side note: Java’s built-in
DataOutputStream.writeUTF()andDataInputStream.readUTF()do something similar, but they use modified UTF-8 and a 2-byte length (max string size: 65535 bytes). For longer strings, stick with the 4-byte int approach above.
Handling Multiple Values: Defining Boundaries in the Byte Array
A byte array is just a continuous stream of bytes—no natural separators. To distinguish values, you need a clear protocol: write values in a fixed order, and use one of two rules for each value:
- Fixed-length types: Primitives like
int(4 bytes),long(8 bytes), orboolean(1 byte) have known sizes. The reader knows exactly how many bytes to grab next. - Length-prefixed types: Variable-length data (strings, arrays, custom objects) get a length marker first, just like we did with strings.
Example: Writing & Reading Multiple Values
Let’s say you want to save a user ID (int), username (String), and last login timestamp (long). Here’s how to structure the byte array:
Writing Code
public static byte[] serializeData(int userId, String username, long lastLogin) throws IOException { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos)) { // Write fixed-length int dos.writeInt(userId); // Write length-prefixed string (using DataOutputStream's built-in method for simplicity) dos.writeUTF(username); // Write fixed-length long dos.writeLong(lastLogin); return baos.toByteArray(); } }
Reading Code
public static void deserializeData(byte[] data) throws IOException { try (ByteArrayInputStream bais = new ByteArrayInputStream(data); DataInputStream dis = new DataInputStream(bais)) { int userId = dis.readInt(); String username = dis.readUTF(); long lastLogin = dis.readLong(); // Use the deserialized data System.out.println("User ID: " + userId); System.out.println("Username: " + username); System.out.println("Last Login Timestamp: " + lastLogin); } }
Why This Works
The reader follows the exact same sequence as the writer: first the 4-byte int, then the length-prefixed string, then the 8-byte long. No guesswork—each value’s boundaries are explicitly defined.
Key Pitfalls to Avoid
- Charset consistency: Always specify the charset (e.g.,
StandardCharsets.UTF_8) when encoding/decoding strings. Skipping this leads to platform-specific bugs. - Length prefix size: For strings over 65535 bytes, avoid
writeUTF()—it uses a 2-byte short that will overflow. Use a 4-byte int instead. - Order matters: The reader must read values in the exact order the writer wrote them. If you change the order later, old saved data will break—document your protocol!
Once you have your byte array, converting to/from Base64 is trivial with Java’s built-in Base64 class:
// Encode byte array to Base64 string for file writing String base64Str = Base64.getEncoder().encodeToString(serializedData); // Decode Base64 string back to byte array byte[] deserializedData = Base64.getDecoder().decode(base64Str);
That’s the core of it! This approach is lightweight, fast, and gives you full control over your data storage—perfect for custom save/load systems.
内容的提问来源于stack exchange,提问作者Ian Rehwinkel

