【问题标题】:Read a segment of a file in Java / Android在 Java / Android 中读取文件的一部分
【发布时间】:2011-04-04 14:52:27
【问题描述】:

我确信这可能是一个简单的问题,但不幸的是,这是我第一次使用 Java 并使用 Android SDK。

我正在使用 Apache HTTP 库在 Android 上上传文件,特别是使用 MultipartEntity。

我正在上传到允许我向他们发送文件块的服务,一旦完成,他们将重新组合这些块。我想利用此功能。

这是场景。

文件 FOO.BAR 为 20 MB。我会将它分成任意大小的块,比如说 1 MB,这意味着 20 个块。块 #3 和 #14 失败(可能蜂窝/WiFi 连接不好)。我现在可以重新上传这两个块,一切都会好起来的。

我想知道的是如何只读取文件的一部分(例如 3MB 和 4MB 之间的数据)?

文件片段应该是 InputStream 或 File 对象。

谢谢, 诚

【问题讨论】:

    标签: java android http file-upload


    【解决方案1】:

    您可以使用skip(long) 方法跳过 InputStream 中的字节数,也可以在 File 对象上创建一个 RandomAccessFile 并调用其seek(long) 方法将指针设置为该位置,以便您开始阅读从那里开始。

    下面的快速测试读取一个 4mb+ 的文件(在 3m 和 4mb 之间)并将读取的数据写入一个".out" 文件。

    import java.io.*;
    import java.util.*;
    
    public class Test {
    
        public static void main(String[] args) throws Throwable {
           long threeMb = 1024 * 1024 * 3;
           File assembled =  new File(args[0]); // your downloaded and assembled file
           RandomAccessFile raf = new RandomAccessFile(assembled, "r"); // read
           raf.seek(threeMb); // set the file pointer to 3mb
           int bytesRead = 0;
           int totalRead = 0;
           int bytesToRead = 1024 * 1024; // 1MB (between 3M and 4M
    
           File f = new File(args[0] + ".out");
           FileOutputStream out = new FileOutputStream(f);
    
           byte[] buffer = new byte[1024 * 128]; // 128k buffer 
           while(totalRead < bytesToRead) { // go on reading while total bytes read is
                                            // less than 1mb
             bytesRead = raf.read(buffer);
             totalRead += bytesRead;
             out.write(buffer, 0, bytesRead);
             System.out.println((totalRead / 1024));
           }
        }
    }
    

    【讨论】:

    • 感谢您提及 RandomAccessFile。这会很有帮助。
    【解决方案2】:

    使用 FileInputStream 流的 skip() 方法寻找你需要的片段。

    【讨论】:

    • 这会告诉它从哪里开始......但我怎么能告诉它只读取 1 MB 的数据而不再继续呢?
    • 那是你在读取字节。数一数你读了多少,读完 1MB 就停下来了。
    【解决方案3】:

    我能够弄清楚...只是发现有一个 ByteArrayInputStream 可以让我将我的 byte[] 缓冲区转换为 InputStream。从这里开始,我现在可以跟踪哪些块失败并处理它。感谢康斯坦丁,这是我的实现:

        final int chunkSize = 512 * 1024; // 512 kB
        final long pieces = file.length() / chunkSize;
        int chunkId = 0;
    
        HttpPost request = new HttpPost(endpoint);
    
        BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
    
        for (chunkId = 0; chunkId < pieces; chunkId++) {
            byte[] buffer = new byte[chunkSize];
    
            stream.skip(chunkId * chunkSize);
            stream.read(buffer);
    
            MultipartEntity entity = new MultipartEntity();
            entity.addPart("chunk_id", new StringBody(String.valueOf(chunkId)));
            request.setEntity(entity);
            ByteArrayInputStream arrayStream = new ByteArrayInputStream(buffer);
    
            entity.addPart("file_data", new InputStreamBody(arrayStream, filename));
    
            HttpClient client = app.getHttpClient();
            client.execute(request);
        }
    

    【讨论】:

      猜你喜欢
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 2015-05-17
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多