You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python读取Java(Android)写入的short/int数组文件

问题背景

我在Android(Java)环境下有两个大型数组,一个是short类型,另一个是int类型,想要把它们写入文件后,在Python中读取并还原成原数组。我原本以为Java侧的写入操作没问题,但Python这边始终无法正确解析文件,求指点怎么解决这个问题。

我的Java写入代码有两种尝试:

Java侧写入代码

方式一:用ObjectOutputStream序列化对象

File mFile = new File( this.getExternalFilesDir(null),"testFile.txt"); 
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(mFile)); 
objectOutputStream.writeObject(intArray); 
objectOutputStream.close();

方式二:循环用OutputStream.write写入

File mFile = new File( this.getExternalFilesDir(null),"testFile.txt"); 
OutputStream outputStream = new FileOutputStream(mFile); 
for (int x: intArray) { 
    outputStream.write(x); 
} 
objectOutputStream.close(); // 这里还有个笔误,应该是outputStream.close()

我尝试用Python的struct库读取,但代码抛出错误:error: unpack requires a buffer of 104 bytes,我的Python代码如下:

with open('/../testFile.txt') as mFile: 
    for ln in mFile: 
        print( list( struct.unpack('I*'(len(ln)//4), ln) ) )

问题分析&解决方案

咱们先把问题拆解清楚:你的Java写入方式其实都存在问题,这才是Python读不对的根源,然后再对应给出正确的读写方案。

1. Java写入的问题在哪?

  • 方式一的坑:ObjectOutputStream是Java专属的对象序列化工具,它写入的不是数组的原始二进制数据,而是包含了Java对象元数据的序列化格式(比如对象类型标识、长度信息等),Python的struct库根本无法解析这种格式,所以肯定读不出来。
  • 方式二的坑:OutputStream.write(int)方法只会写入这个int值的最低8位(一个字节),而Java的int是4字节的,这样写会直接丢掉高24位的数据,导致数组内容完全损坏。比如你测试的1000,二进制是00000000 00000000 00000011 11101000,用write(x)只会写入最后一个字节11101000(对应十进制232),数据完全变了。

2. 正确的Java写入方式

要让Python能正确读取,Java必须把数组写成原始的二进制字节流,每个元素按固定字节数写入(int占4字节,short占2字节),推荐用DataOutputStream,它专门用来写入Java基本数据类型的二进制值:

写入int数组

File mFile = new File(this.getExternalFilesDir(null), "int_array.bin");
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(mFile))) {
    // 先写入数组长度,方便Python读取时知道要读多少个元素
    dos.writeInt(intArray.length);
    for (int num : intArray) {
        dos.writeInt(num); // 每个int写4字节,默认大端字节序
    }
} catch (IOException e) {
    e.printStackTrace();
}

写入short数组

File mFile = new File(this.getExternalFilesDir(null), "short_array.bin");
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(mFile))) {
    // 用int存储数组长度,避免short的范围限制(如果数组很大的话)
    dos.writeInt(shortArray.length);
    for (short num : shortArray) {
        dos.writeShort(num); // 每个short写2字节,默认大端字节序
    }
} catch (IOException e) {
    e.printStackTrace();
}

3. 对应的Python读取代码

注意要以二进制模式打开文件(rb),因为我们写的是二进制数据,不是文本。另外Java默认用大端字节序(big-endian),所以Python的struct格式符要加前缀>指定字节序。

读取int数组

import struct

# 替换成你的文件实际路径
with open('/storage/emulated/0/Android/data/[你的包名]/files/int_array.bin', 'rb') as f:
    # 先读取数组长度(4字节的int)
    length_bytes = f.read(4)
    array_length = struct.unpack('>I', length_bytes)[0]
    # 读取所有int元素的二进制数据,每个占4字节
    int_bytes = f.read(array_length * 4)
    # 解析成int数组
    int_array = list(struct.unpack(f'>{array_length}I', int_bytes))
    print("还原的int数组:", int_array)

读取short数组

import struct

with open('/storage/emulated/0/Android/data/[你的包名]/files/short_array.bin', 'rb') as f:
    length_bytes = f.read(4)
    array_length = struct.unpack('>I', length_bytes)[0]
    short_bytes = f.read(array_length * 2)
    # 格式符h对应short类型,>指定大端字节序
    short_array = list(struct.unpack(f'>{array_length}h', short_bytes))
    print("还原的short数组:", short_array)

4. 你之前Python代码的错误点

  • 没有用二进制模式打开文件:open('/../testFile.txt')默认是文本模式,会把二进制数据当成文本处理,导致数据截断或乱码,必须加rb。
  • 循环读取“行”:二进制文件没有文本文件的“行”概念,这样读取会把连续的二进制数据拆成错误的块。
  • 格式符语法错误:'I*'(len(ln)//4)是错误的写法,应该用动态格式字符串,比如f'>{count}I'来指定要解析的元素数量。

内容的提问来源于stack exchange,提问作者Shyam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 08:22:38