java – 使用BlockingQueue的PDF文件下载

前端之家收集整理的这篇文章主要介绍了java – 使用BlockingQueue的PDF文件下载前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试使用URLConnection下载一个pdf文件.以下是我如何设置连接对象.
URL serverUrl = new URL(url);
urlConnection = (HttpURLConnection) serverUrl.openConnection();
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Content-Type","application/pdf");
urlConnection.setRequestProperty("ENCTYPE","multipart/form-data");
String contentLength = urlConnection.getHeaderField("Content-Length");

我从连接对象获取输入流.

bufferedInputStream = new BufferedInputStream(urlConnection.getInputStream());

输出流写入文件内容.

File dir = new File(context.getFilesDir(),mFolder);
if(!dir.exists()) dir.mkdir();
final File f = new File(dir,String.valueOf(documentName));
f.createNewFile();
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(f,true)); //true for appendMode

BlockingQueue被创建,以便执行读写操作的线程可以访问队列.

final BlockingQueue<ByteArrayWrapper> blockingQueue = new ArrayBlockingQueue<ByteArrayWrapper>(MAX_VALUE,true);
final byte[] dataBuffer = new byte[MAX_VALUE];

现在创建线程从InputStream读取数据.

Thread readerThread = new Thread(new Runnable() {
       @Override
       public void run() {
         try {
            int count = 0;
            while((count = bufferedInputStream.read(dataBuffer,dataBuffer.length)) != -1) {
                 ByteArrayWrapper byteArrayWrapper = new ByteArrayWrapper(dataBuffer);
                 byteArrayWrapper.setBytesReadCount(count);
                 blockingQueue.put(byteArrayWrapper);
             }
             blockingQueue.put(null); //end of file
          } catch(Exception e) {
                 e.printStackTrace();
          } finally {
              try {
                 bufferedInputStream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
       }
 });

现在,作者线程读取这些文件内容.

Thread writerThread = new Thread(new Runnable() {
       @Override
       public void run() {
         try {
            while(true) {
               ByteArrayWrapper byteWrapper = blockingQueue.take();
               if(null == byteWrapper) break;
               bufferedOutputStream.write(byteWrapper.getBytesRead(),byteWrapper.getBytesReadCount());
             }
             bufferedOutputStream.flush();
         } catch(Exception e) {
              e.printStackTrace();
         } finally {
              try {
                 bufferedOutputStream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
         }
      }
});

最后,启动线程.

readerThread.start();
writerThread.start();

理论上它应该从InputStream读取文件并将其保存到目标文件中.然而,实际上它生成空白的pdf文件.在其他时间,它显示无效的pdf格式异常.文件大小与InputStream的内容长度相匹配.有什么我错过的吗?

解决方法

我不熟悉ByteArrayWrapper.它只是持有对数组的引用,像这样吗?
public class ByteArrayBuffer {
    final private byte[] data;

    public ByteArrayBuffer(byte[] data) {
        this.data = data;
    }

    public byte[] getBytesRead() {
        return data;
    }

    /*...etc...*/
}

如果是这样.这将是问题:所有ByteArrayWrapper对象都由相同的数组支持.作者一再被覆盖.即使BlockingQueue也努力将每个对象从一个线程安全地发布到另一个线程.

最简单的修复可能是使ByteArrayWrapper有效地不变,即在将其发布到另一个线程之后不要更改它.在构建阵列的副本将是最简单的:

public ByteArrayWrapper(byte[] data) {
    this.data = Arrays.copyOf(data,data.length);
}

另一个问题是“BlockingQueue不接受空元素”(见BlockingQueue docs),因此“输入结束”哨兵值不起作用.用a替换null

private static ByteArrayWrapper END = new ByteArrayWrapper(new byte[]{});

在适当的地方会解决这个问题.

通过对代码的副本进行这些更改,我能够检索PDF文件的忠实副本.

原文链接:https://www.f2er.com/java/125692.html

猜你在找的Java相关文章