|
5 | 5 | import android.graphics.Bitmap; |
6 | 6 | import android.graphics.BitmapFactory; |
7 | 7 | import android.graphics.drawable.BitmapDrawable; |
| 8 | +import android.net.Uri; |
8 | 9 | import android.os.Looper; |
9 | 10 | import android.util.Base64; |
10 | 11 | import android.util.Log; |
|
13 | 14 | import java.io.ByteArrayOutputStream; |
14 | 15 | import java.io.Closeable; |
15 | 16 | import java.io.DataInputStream; |
| 17 | +import java.io.File; |
16 | 18 | import java.io.FileInputStream; |
17 | 19 | import java.io.FileNotFoundException; |
18 | 20 | import java.io.FileOutputStream; |
|
29 | 31 | import java.nio.ByteBuffer; |
30 | 32 | import java.nio.CharBuffer; |
31 | 33 | import java.nio.channels.FileChannel; |
| 34 | +import java.nio.channels.ReadableByteChannel; |
| 35 | +import java.nio.channels.WritableByteChannel; |
32 | 36 | import java.util.ArrayList; |
33 | 37 | import java.util.List; |
34 | 38 | import java.util.Locale; |
@@ -595,6 +599,94 @@ private void closeOpenedStreams(Stack<Closeable> streams) throws IOException { |
595 | 599 |
|
596 | 600 | public static class File { |
597 | 601 |
|
| 602 | + public static boolean copySync(final String src, final String dest, final Context context) throws Exception { |
| 603 | + InputStream is; |
| 604 | + OutputStream os; |
| 605 | + |
| 606 | + if(src.startsWith("content://")){ |
| 607 | + is = context.getContentResolver().openInputStream(Uri.parse(src)); |
| 608 | + }else is = new FileInputStream(new java.io.File(src)); |
| 609 | + |
| 610 | + if(dest.startsWith("content://")){ |
| 611 | + os = context.getContentResolver().openOutputStream(Uri.parse(dest)); |
| 612 | + }else os = new FileOutputStream(new java.io.File(dest)); |
| 613 | + |
| 614 | + return copySync(is, os, context); |
| 615 | + } |
| 616 | + |
| 617 | + public static boolean copySync(final InputStream src, final OutputStream dest, final Object context) throws Exception { |
| 618 | + ReadableByteChannel isc = java.nio.channels.Channels.newChannel(src); |
| 619 | + WritableByteChannel osc = java.nio.channels.Channels.newChannel(dest); |
| 620 | + |
| 621 | + int size = src.available(); |
| 622 | + |
| 623 | + int written = fastChannelCopy(isc, osc); |
| 624 | + |
| 625 | + return size == written; |
| 626 | + } |
| 627 | + |
| 628 | + public static void copy(final String src, final String dest, final CompleteCallback callback, final Context context) { |
| 629 | + try { |
| 630 | + InputStream is; |
| 631 | + OutputStream os; |
| 632 | + |
| 633 | + if(src.startsWith("content://")){ |
| 634 | + is = context.getContentResolver().openInputStream(Uri.parse(src)); |
| 635 | + }else is = new FileInputStream(new java.io.File(src)); |
| 636 | + |
| 637 | + if(dest.startsWith("content://")){ |
| 638 | + os = context.getContentResolver().openOutputStream(Uri.parse(dest)); |
| 639 | + }else os = new FileOutputStream(new java.io.File(dest)); |
| 640 | + |
| 641 | + copy(is, os, callback, context); |
| 642 | + }catch (Exception exception){ |
| 643 | + callback.onError(exception.getMessage(), context); |
| 644 | + } |
| 645 | + } |
| 646 | + |
| 647 | + private static int fastChannelCopy(final ReadableByteChannel src, |
| 648 | + final WritableByteChannel dest) throws IOException { |
| 649 | + int written = 0; |
| 650 | + final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); |
| 651 | + while (src.read(buffer) != -1) { |
| 652 | + // prepare the buffer to be drained |
| 653 | + buffer.flip(); |
| 654 | + // write to the channel, may block |
| 655 | + written += dest.write(buffer); |
| 656 | + // If partial transfer, shift remainder down |
| 657 | + // If buffer is empty, same as doing clear() |
| 658 | + buffer.compact(); |
| 659 | + } |
| 660 | + // EOF will leave buffer in fill state |
| 661 | + buffer.flip(); |
| 662 | + // make sure the buffer is fully drained. |
| 663 | + while (buffer.hasRemaining()) { |
| 664 | + written += dest.write(buffer); |
| 665 | + } |
| 666 | + return written; |
| 667 | + } |
| 668 | + |
| 669 | + |
| 670 | + public static void copy(final InputStream src, final OutputStream dest, final CompleteCallback callback, final Object context) { |
| 671 | + final android.os.Handler mHandler = new android.os.Handler(Looper.myLooper()); |
| 672 | + threadPoolExecutor().execute((Runnable) () -> { |
| 673 | + |
| 674 | + try (InputStream is = src; OutputStream os = dest){ |
| 675 | + ReadableByteChannel isc = java.nio.channels.Channels.newChannel(is); |
| 676 | + WritableByteChannel osc = java.nio.channels.Channels.newChannel(os); |
| 677 | + |
| 678 | + int size = src.available(); |
| 679 | + |
| 680 | + int written = fastChannelCopy(isc, osc); |
| 681 | + |
| 682 | + mHandler.post(() -> callback.onComplete(size == written, context)); |
| 683 | + |
| 684 | + } catch (Exception e) { |
| 685 | + mHandler.post(() -> callback.onError(e.getMessage(), context)); |
| 686 | + } |
| 687 | + }); |
| 688 | + } |
| 689 | + |
598 | 690 | public static void readText(final String path, final String encoding, final CompleteCallback callback, final Object context) { |
599 | 691 | final android.os.Handler mHandler = new android.os.Handler(Looper.myLooper()); |
600 | 692 | threadPoolExecutor().execute(new Runnable() { |
|
0 commit comments