From 74aba3d8ff34ed0c19511064882aea5f7d9d6fa6 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Sun, 15 Jan 2023 07:23:44 -0500 Subject: [PATCH] improve input stream read performance --- .../lib/arsc/chunk/UnknownChunk.java | 46 ++++++------- .../reandroid/lib/arsc/header/AnyHeader.java | 47 +------------ .../lib/arsc/header/HeaderBlock.java | 67 +++++++++++++++++-- .../reandroid/lib/arsc/io/BlockReader.java | 14 ++-- .../lib/arsc/pool/TableStringPool.java | 17 +++-- 5 files changed, 100 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java b/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java index 8d9548e..1d63da7 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java @@ -16,7 +16,6 @@ package com.reandroid.lib.arsc.chunk; import com.reandroid.lib.arsc.header.HeaderBlock; - import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.ByteArray; import java.io.*; @@ -26,30 +25,25 @@ package com.reandroid.lib.arsc.chunk; * handle any future android changes * */ public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded { - private final ByteArray headerExtra; private final ByteArray body; public UnknownChunk() { super(INITIAL_CHUNK_TYPE, 1); - this.headerExtra = new ByteArray(); this.body = new ByteArray(); - - addToHeader(this.headerExtra); addChild(body); - setHeaderLoaded(this); } + public ByteArray getBody(){ + return body; + } @Override public void onChunkTypeLoaded(short type) { } @Override public void onHeaderSizeLoaded(int headerSize) { - int extraSize = headerSize - 8; - this.headerExtra.setSize(extraSize); } @Override public void onChunkSizeLoaded(int headerSize, int chunkSize) { - int bodySize = chunkSize - headerSize; - this.body.setSize(bodySize); + getBody().setSize(chunkSize - headerSize); } @Override @@ -68,18 +62,25 @@ public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded } return os.toByteArray(); } - public void readBytes(File file) throws IOException{ - BlockReader reader=new BlockReader(file); - super.readBytes(reader); + public int readBytes(File file) throws IOException{ + FileInputStream inputStream=new FileInputStream(file); + int result=readBytes(inputStream); + inputStream.close(); + return result; } - public void readBytes(InputStream inputStream) throws IOException{ - BlockReader reader=new BlockReader(inputStream); - super.readBytes(reader); + public int readBytes(InputStream inputStream) throws IOException{ + int result; + result=getHeaderBlock().readBytes(inputStream); + result+=getBody().readBytes(inputStream); + super.notifyBlockLoad(); + return result; } public final int writeBytes(File file) throws IOException{ File dir=file.getParentFile(); if(dir!=null && !dir.exists()){ - dir.mkdirs(); + if(dir.mkdirs()){ + throw new IOException("Can not create directory: "+dir); + } } OutputStream outputStream=new FileOutputStream(file); int length = super.writeBytes(outputStream); @@ -88,15 +89,10 @@ public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded } @Override public String toString(){ - HeaderBlock headerBlock = getHeaderBlock(); - return getClass().getSimpleName() - +"{ type="+String.format("0x%04x", headerBlock.getType()) - +", chunkSize="+headerBlock.getChunkSize() - +", headerExtra="+headerExtra.size() - +", body="+body.size()+"}"; + return getHeaderBlock() + +" {Body="+getBody().size()+"}"; } - // This value must not exist is ChunkType enum list - private static final short INITIAL_CHUNK_TYPE = 0x0207; + private static final short INITIAL_CHUNK_TYPE = 0x0000; } diff --git a/src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java b/src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java index 584da6d..a5767a1 100644 --- a/src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java +++ b/src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java @@ -15,55 +15,12 @@ */ package com.reandroid.lib.arsc.header; -import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.chunk.ChunkType; -import com.reandroid.lib.arsc.item.BlockItem; -import com.reandroid.lib.arsc.item.ByteArray; - -import java.io.IOException; -import java.io.InputStream; +/**No importance of this class, to be removed latter*/ +@Deprecated public class AnyHeader extends HeaderBlock{ public AnyHeader() { super(ChunkType.NULL.ID); } - public int readBytes(InputStream inputStream) throws IOException { - int result=0; - Block[] childes = getChildes(); - for(Block child:childes){ - if(child instanceof BlockItem){ - BlockItem blockItem=(BlockItem) child; - result += blockItem.readBytes(inputStream); - } - } - return result; - } - public byte[] readChunkBytes(InputStream inputStream) throws IOException{ - int chunkSize = getChunkSize(); - int headerSize = getHeaderSize(); - if(chunkSize < 0 || chunkSize < headerSize){ - throw new IOException("Invalid chunk size: " + super.toString()); - } - byte[] buffer = new byte[chunkSize]; - int length = chunkSize - headerSize; - int offset = loadHeaderBytes(buffer); - while (length>0){ - int len = inputStream.read(buffer, offset, length); - length=length-len; - offset=offset+len; - } - return buffer; - } - private int loadHeaderBytes(byte[] buffer){ - int index=0; - Block[] childes = getChildes(); - for(Block child:childes){ - byte[] childBytes=child.getBytes(); - for(int i=0;i childes= + ((BlockList) block).getChildes(); + for(Block child:childes){ + result+=readBytes(inputStream, child); + } + }else if(block instanceof BlockContainer){ + Block[] childes = + ((BlockContainer) block).getChildes(); + for(Block child:childes){ + result+=readBytes(inputStream, child); + } + }else { + throw new IOException("Can not read block type: "+block.getClass()); + } + return result; + } @Override public void onReadBytes(BlockReader reader) throws IOException { int start=reader.getPosition(); @@ -155,14 +202,14 @@ import java.io.IOException; @Override public String toString(){ - short t= getType(); - ChunkType type= ChunkType.get(t); - StringBuilder builder=new StringBuilder(); + short t = getType(); + ChunkType type = ChunkType.get(t); + StringBuilder builder = new StringBuilder(); if(type!=null){ builder.append(type.toString()); }else { builder.append("Unknown type="); - builder.append(String.format("0x%02x", ((int)t))); + builder.append(String.format("0x%02x", (0xffff & t))); } builder.append("{Header="); builder.append(getHeaderSize()); @@ -172,6 +219,18 @@ import java.io.IOException; return builder.toString(); } + public static HeaderBlock readHeaderBlock(File file) throws IOException{ + InputStream inputStream = new FileInputStream(file); + HeaderBlock headerBlock = readHeaderBlock(inputStream); + inputStream.close(); + return headerBlock; + } + public static HeaderBlock readHeaderBlock(InputStream inputStream) throws IOException { + HeaderBlock headerBlock=new HeaderBlock(ChunkType.NULL.ID); + headerBlock.readBytes(inputStream); + return headerBlock; + } + public interface HeaderLoaded{ void onChunkTypeLoaded(short type); void onHeaderSizeLoaded(int headerSize); diff --git a/src/main/java/com/reandroid/lib/arsc/io/BlockReader.java b/src/main/java/com/reandroid/lib/arsc/io/BlockReader.java index f5c20d5..6c90bc8 100755 --- a/src/main/java/com/reandroid/lib/arsc/io/BlockReader.java +++ b/src/main/java/com/reandroid/lib/arsc/io/BlockReader.java @@ -15,7 +15,6 @@ */ package com.reandroid.lib.arsc.io; -import com.reandroid.lib.arsc.header.AnyHeader; import com.reandroid.lib.arsc.header.HeaderBlock; import java.io.*; @@ -309,15 +308,10 @@ import java.io.*; } return buff; } - public static AnyHeader readHeaderBlock(File file) throws IOException{ - InputStream inputStream=new FileInputStream(file); - AnyHeader anyHeader = readHeaderBlock(inputStream); - inputStream.close(); - return anyHeader; + public static HeaderBlock readHeaderBlock(File file) throws IOException{ + return HeaderBlock.readHeaderBlock(file); } - public static AnyHeader readHeaderBlock(InputStream inputStream) throws IOException{ - AnyHeader anyHeader=new AnyHeader(); - anyHeader.readBytes(inputStream); - return anyHeader; + public static HeaderBlock readHeaderBlock(InputStream inputStream) throws IOException{ + return HeaderBlock.readHeaderBlock(inputStream); } } diff --git a/src/main/java/com/reandroid/lib/arsc/pool/TableStringPool.java b/src/main/java/com/reandroid/lib/arsc/pool/TableStringPool.java index facab0e..ac4e8e7 100755 --- a/src/main/java/com/reandroid/lib/arsc/pool/TableStringPool.java +++ b/src/main/java/com/reandroid/lib/arsc/pool/TableStringPool.java @@ -18,7 +18,8 @@ package com.reandroid.lib.arsc.pool; import com.reandroid.lib.arsc.array.StringArray; import com.reandroid.lib.arsc.array.TableStringArray; import com.reandroid.lib.arsc.chunk.ChunkType; -import com.reandroid.lib.arsc.header.AnyHeader; +import com.reandroid.lib.arsc.chunk.UnknownChunk; +import com.reandroid.lib.arsc.header.HeaderBlock; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.IntegerArray; import com.reandroid.lib.arsc.item.IntegerItem; @@ -57,19 +58,21 @@ import java.io.InputStream; } /** - * Loads string pool from table block (resources.arsc) + * Loads string pool only from table block (resources.arsc) without + * loading other chunks */ public static TableStringPool readFromTable(InputStream inputStream) throws IOException { - AnyHeader tableHeader = BlockReader.readHeaderBlock(inputStream); + HeaderBlock tableHeader = HeaderBlock.readHeaderBlock(inputStream); if(tableHeader.getChunkType()!=ChunkType.TABLE){ throw new IOException("Not TableBlock: "+tableHeader); } - AnyHeader poolHeader = BlockReader.readHeaderBlock(inputStream); + UnknownChunk poolChunk = new UnknownChunk(); + poolChunk.readBytes(inputStream); + HeaderBlock poolHeader = poolChunk.getHeaderBlock(); if(poolHeader.getChunkType()!=ChunkType.STRING){ - throw new IOException("Not StringPool: "+poolHeader); + throw new IOException("Not StringPool chunk: " + poolChunk); } - byte[] poolBytes = poolHeader.readChunkBytes(inputStream); - BlockReader blockReader = new BlockReader(poolBytes); + BlockReader blockReader = new BlockReader(poolChunk.getBytes()); TableStringPool stringPool = new TableStringPool(true); stringPool.readBytes(blockReader); blockReader.close();