【问题标题】:Read python pickle data stream in Android在Android中读取python pickle数据流
【发布时间】:2014-02-15 07:32:59
【问题描述】:

我有这个文件,其中包含 python pickle 数据流。我必须在 Android 中读取此文件的内容。

例如,如果我想在python中读取这个数据流,我只需使用以下代码

queue = pickle.load(open('filename', 'rb'))

我想在 Android 中实现同样的功能,这样我就可以读取这个 pickle 流数据并将其存储在某种集合中。

我怎样才能做到这一点?

【问题讨论】:

    标签: android python pickle


    【解决方案1】:

    更新:这仅适用于泡菜协议 23

    我认为来自Pyrolite(MIT 许可证)的Unpickler 类可能对您特别感兴趣。它在技术上是 Java,但 Android 基本上是 Java。要取消腌制,您将执行类似于以下的操作:

    InputStream stream = new FileInputStream("filename");
    Unpickler unpickler = new Unpickler();
    Object data = unpickler.load(stream);
    // And cast *data* to the appropriate type.
    

    进口:

    import java.io.FileInputStream;
    import java.io.InputStream;
    import net.razorvine.pickle.Unpickler;
    

    这些是默认支持的对象:

    PYTHON    ---->     JAVA
    ------              ----
    None                null
    bool                boolean
    int                 int
    long                long or BigInteger  (depending on size)
    string              String
    unicode             String
    complex             net.razorvine.pickle.objects.ComplexNumber
    datetime.date       java.util.Calendar
    datetime.datetime   java.util.Calendar
    datetime.time       java.util.Calendar
    datetime.timedelta  net.razorvine.pickle.objects.TimeDelta
    float               double   (float isn't used) 
    array.array         array of appropriate primitive type (char, int, short, long, float, double)
    list                java.util.List<Object>
    tuple               Object[]
    set                 java.util.Set
    dict                java.util.Map
    bytes               byte[]
    bytearray           byte[]
    decimal             BigDecimal    
    custom class        Map<String, Object>  (dict with class attributes including its name in "__class__")
    

    另请注意:

    unpickler 只返回一个对象。因为Java是静态类型的 语言,您必须将其转换为适当的类型。参考这个 表,看看你能收到什么。


    更新:我使用各种 pickle 协议 (0-3) 运行测试,发现 01 失败,但 23 成功。

    这是用于生成腌制数据的python代码:

    import pickle
    
    class Data(object):
        def __init__(self):
            self.x = 12
    
    data = Data()
    
    for p in [0, 1, 2]:
        with open('data.{}'.format(p), 'wb') as fh:
            pickle.dump(data, fh, protocol=p)
    
    # Python 3 only.
    with open('data.3', 'wb') as fh:
        pickle.dump(data, fh, protocol=3)
    

    还有解压它的java代码:

    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.IOException;
    import java.util.Map;
    import net.razorvine.pickle.Unpickler;
    
    public class Test {
        public static void main(String[] args) throws IOException {
            String filename = args[0];
            InputStream inputStream = new FileInputStream(filename);
            Unpickler unpickler = new Unpickler();
            Map<String, Object> data = (Map<String, Object>)unpickler.load(inputStream);
        }
    }
    

    当使用data.0data.1 运行时,它会失败并显示:

    Exception in thread "main" net.razorvine.pickle.PickleException: expected zero arguments for construction of ClassDict (for copy_reg._reconstructor)
      at net.razorvine.pickle.objects.ClassDictConstructor.construct(ClassDictConstructor.java:23)
      at net.razorvine.pickle.Unpickler.load_reduce(Unpickler.java:617)
      at net.razorvine.pickle.Unpickler.dispatch(Unpickler.java:170)
      at net.razorvine.pickle.Unpickler.load(Unpickler.java:84)
      at Test.main(Test.java:13)
    

    当使用data.2data.3 运行时,它会成功。

    【讨论】:

    • 感谢您的回复。这看起来很有希望。我的泡菜数据流包含自定义类。所以,我像这样使用它 Object data = (Map&lt;String, Entry&gt;)unpickler.load(inputStream); 这给了我一个错误 net.razorvine.pickle.PickleException: expected zero arguments for construction of ClassDict 。我在这里做错了吗?
    • @RajeshGolani 看起来您需要在 python 端使用协议23 进行腌制才能使其工作。查看我的更新了解更多详情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多