Procházet zdrojové kódy

修复中文AndroidZipFile不能读取非ASCII字符文件名

ag2s20150909 před 3 roky
rodič
revize
d9421ebe69

+ 18 - 2
app/src/main/java/io/legado/app/lib/icu4j/CharsetDetector.java

@@ -8,6 +8,10 @@
  */
 package io.legado.app.lib.icu4j;
 
+import android.os.ParcelFileDescriptor;
+import android.system.OsConstants;
+
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import java.io.IOException;
@@ -88,13 +92,25 @@ public class CharsetDetector {
      * @return This CharsetDetector
      * @stable ICU 3.4
      */
-    public CharsetDetector setText(byte[] in) {
+    public CharsetDetector setText(@NonNull byte[] in) {
         fRawInput = in;
         fRawLength = in.length;
 
         return this;
     }
 
+    public CharsetDetector setText(@NonNull ParcelFileDescriptor pfd) {
+        fRawInput = new byte[kBufSize];
+        try {
+            android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_SET);
+            fRawLength = android.system.Os.read(pfd.getFileDescriptor(), fRawInput, 0, fRawInput.length);
+            android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_SET);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return this;
+    }
+
     private static final int kBufSize = 8000;
 
     /**
@@ -111,7 +127,7 @@ public class CharsetDetector {
      * @stable ICU 3.4
      */
 
-    public CharsetDetector setText(InputStream in) throws IOException {
+    public CharsetDetector setText(@NonNull InputStream in) throws IOException {
         fInputStream = in;
         fInputStream.mark(kBufSize);
         fRawInput = new byte[kBufSize];   // Always make a new buffer because the

+ 1 - 1
epublib/src/main/java/me/ag2s/base/PfdHelper.java

@@ -39,7 +39,7 @@ public final class PfdHelper {
 
     public static long length(ParcelFileDescriptor pfd) throws IOException {
         try {
-            return android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_END);
+            return android.system.Os.fstat(pfd.getFileDescriptor()).st_size; //android.system.Os.lseek(pfd.getFileDescriptor(), 0, OsConstants.SEEK_END);
         } catch (ErrnoException e) {
             throw rethrowAsIOException(e);
         }

+ 12 - 4
epublib/src/main/java/me/ag2s/epublib/util/zip/AndroidZipEntry.java

@@ -24,6 +24,7 @@ public class AndroidZipEntry implements ZipConstants, Cloneable {
   private static Calendar cal;
 
   private final String name;
+  private final int nameLen;
   private int size;
   private int compressedSize;
   private int crc;
@@ -54,13 +55,15 @@ public class AndroidZipEntry implements ZipConstants, Cloneable {
    * @throws NullPointerException     when name is null.
    * @throws IllegalArgumentException when name is bigger then 65535 chars.
    */
-  public AndroidZipEntry(String name) {
-    int length = name.length();
-    if (length > 65535)
-      throw new IllegalArgumentException("name length is " + length);
+  public AndroidZipEntry(String name, int nameLen) {
+    //int length = name.length();
+    this.nameLen = nameLen;
+    if (nameLen > 65535)
+      throw new IllegalArgumentException("name length is " + nameLen);
     this.name = name;
   }
 
+
   /**
    * Creates a copy of the given zip entry.
    *
@@ -68,6 +71,7 @@ public class AndroidZipEntry implements ZipConstants, Cloneable {
    */
   public AndroidZipEntry(AndroidZipEntry e) {
     name = e.name;
+    nameLen = e.nameLen;
     known = e.known;
     size = e.size;
     compressedSize = e.compressedSize;
@@ -116,6 +120,10 @@ public class AndroidZipEntry implements ZipConstants, Cloneable {
     return name;
   }
 
+  public int getNameLen() {
+    return nameLen;
+  }
+
   /**
    * Sets the time of last modification of the entry.
    *

+ 4 - 4
epublib/src/main/java/me/ag2s/epublib/util/zip/AndroidZipFile.java

@@ -242,9 +242,9 @@ public class AndroidZipFile implements ZipConstants {
                 buffer = new byte[needBuffer];
 
             PfdHelper.readFully(pfd, buffer, 0, nameLen);
-            String name = new String(buffer, 0, 0, nameLen);
+            String name = new String(buffer, 0, nameLen);
 
-            AndroidZipEntry entry = new AndroidZipEntry(name);
+            AndroidZipEntry entry = new AndroidZipEntry(name, nameLen);
             entry.setMethod(method);
             entry.setCrc(crc & 0xffffffffL);
             entry.setSize(size & 0xffffffffL);
@@ -361,10 +361,10 @@ public class AndroidZipFile implements ZipConstants {
             if (entry.getMethod() != readLeShort(locBuf, LOCHOW))
                 throw new ZipException("Compression method mismatch: " + name);
 
-            if (entry.getName().length() != readLeShort(locBuf, LOCNAM))
+            if (entry.getNameLen() != readLeShort(locBuf, LOCNAM))
                 throw new ZipException("file name length mismatch: " + name);
 
-            int extraLen = entry.getName().length() + readLeShort(locBuf, LOCEXT);
+            int extraLen = entry.getNameLen() + readLeShort(locBuf, LOCEXT);
             return entry.offset + LOCHDR + extraLen;
         }
     }